💄 Updated extended management interface style and keybinding management interface style
@@ -461,6 +461,11 @@ export class GeneralConfig {
|
|||||||
*/
|
*/
|
||||||
"enableTabs": boolean;
|
"enableTabs": boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用内存监视器
|
||||||
|
*/
|
||||||
|
"enableMemoryMonitor": boolean;
|
||||||
|
|
||||||
/** Creates a new GeneralConfig instance. */
|
/** Creates a new GeneralConfig instance. */
|
||||||
constructor($$source: Partial<GeneralConfig> = {}) {
|
constructor($$source: Partial<GeneralConfig> = {}) {
|
||||||
if (!("alwaysOnTop" in $$source)) {
|
if (!("alwaysOnTop" in $$source)) {
|
||||||
@@ -490,6 +495,9 @@ export class GeneralConfig {
|
|||||||
if (!("enableTabs" in $$source)) {
|
if (!("enableTabs" in $$source)) {
|
||||||
this["enableTabs"] = false;
|
this["enableTabs"] = false;
|
||||||
}
|
}
|
||||||
|
if (!("enableMemoryMonitor" in $$source)) {
|
||||||
|
this["enableMemoryMonitor"] = false;
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(this, $$source);
|
Object.assign(this, $$source);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,13 +89,21 @@ export function UpdateKeyBindingEnabled(id: number, enabled: boolean): Promise<v
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UpdateKeyBindingKeys 更新快捷键绑定(根据操作系统自动判断更新哪个字段)
|
* UpdateKeyBindingKeys 更新快捷键绑定
|
||||||
*/
|
*/
|
||||||
export function UpdateKeyBindingKeys(id: number, key: string): Promise<void> & { cancel(): void } {
|
export function UpdateKeyBindingKeys(id: number, key: string): Promise<void> & { cancel(): void } {
|
||||||
let $resultPromise = $Call.ByID(3432755175, id, key) as any;
|
let $resultPromise = $Call.ByID(3432755175, id, key) as any;
|
||||||
return $resultPromise;
|
return $resultPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UpdateKeyBindingPreventDefault 更新快捷键 PreventDefault 状态
|
||||||
|
*/
|
||||||
|
export function UpdateKeyBindingPreventDefault(id: number, preventDefault: boolean): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(202386744, id, preventDefault) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
// Private type creation functions
|
// Private type creation functions
|
||||||
const $$createType0 = models$0.KeyBinding.createFrom;
|
const $$createType0 = models$0.KeyBinding.createFrom;
|
||||||
const $$createType1 = $Create.Array($$createType0);
|
const $$createType1 = $Create.Array($$createType0);
|
||||||
|
|||||||
2
frontend/components.d.ts
vendored
@@ -11,6 +11,8 @@ export {}
|
|||||||
/* prettier-ignore */
|
/* prettier-ignore */
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
|
AccordionContainer: typeof import('./src/components/accordion/AccordionContainer.vue')['default']
|
||||||
|
AccordionItem: typeof import('./src/components/accordion/AccordionItem.vue')['default']
|
||||||
BlockLanguageSelector: typeof import('./src/components/toolbar/BlockLanguageSelector.vue')['default']
|
BlockLanguageSelector: typeof import('./src/components/toolbar/BlockLanguageSelector.vue')['default']
|
||||||
DocumentSelector: typeof import('./src/components/toolbar/DocumentSelector.vue')['default']
|
DocumentSelector: typeof import('./src/components/toolbar/DocumentSelector.vue')['default']
|
||||||
LinuxTitleBar: typeof import('./src/components/titlebar/LinuxTitleBar.vue')['default']
|
LinuxTitleBar: typeof import('./src/components/titlebar/LinuxTitleBar.vue')['default']
|
||||||
|
|||||||
1
frontend/public/images/blockImage.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg t="1767366893329" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="106998" width="200" height="200"><path d="M344.064 36.571429v95.085714H155.428571a23.771429 23.771429 0 0 0-23.259428 19.017143l-0.512 4.754285-0.073143 509.952L306.176 505.417143a95.085714 95.085714 0 0 1 121.270857-5.997714l4.827429 3.876571 152.137143 130.413714 102.546285-102.4a95.085714 95.085714 0 0 1 119.003429-12.507428l5.266286 3.657143 81.042285 60.781714 0.073143-118.784 0.512-7.021714a47.542857 47.542857 0 0 1 94.061714 0l0.512 7.021714v404.114286c0 62.171429-47.762286 113.225143-108.617142 118.418285l-10.24 0.438857h-713.142858l-10.24-0.438857a118.857143 118.857143 0 0 1-108.105142-107.52L36.571429 868.498286v-713.142857l0.438857-10.24A118.857143 118.857143 0 0 1 155.428571 36.571429h188.708572z m26.331429 538.916571L131.657143 794.404571l0.073143 74.166858c0 11.483429 8.118857 21.065143 19.017143 23.259428l4.754285 0.512h713.142857a23.771429 23.771429 0 0 0 23.259429-19.017143l0.512-4.754285-0.073143-166.473143-138.093714-103.570286-97.353143 97.28 76.288 65.316571a47.542857 47.542857 0 0 1-58.002286 75.190858l-3.876571-2.925715-300.836572-257.901714zM649.069714 60.269714a47.542857 47.542857 0 0 1 3.291429 63.634286l-3.291429 3.657143-61.44 61.44 61.44 61.44a47.542857 47.542857 0 0 1 3.291429 63.634286l-3.291429 3.657142a47.542857 47.542857 0 0 1-63.634285 3.218286l-3.584-3.291428-95.085715-95.085715a47.542857 47.542857 0 0 1-3.291428-63.634285l3.291428-3.584 95.085715-95.085715a47.542857 47.542857 0 0 1 67.291428 0zM855.259429 57.051429l3.584 3.218285 95.085714 95.085715a47.542857 47.542857 0 0 1 3.291428 63.634285l-3.291428 3.657143-95.085714 95.085714a47.542857 47.542857 0 0 1-70.509715-63.634285l3.291429-3.657143 61.44-61.44-61.44-61.44a47.542857 47.542857 0 0 1-3.291429-63.634286l3.291429-3.657143a47.542857 47.542857 0 0 1 63.634286-3.218285zM344.210286 36.571429a47.542857 47.542857 0 0 1 7.021714 94.573714l-7.021714 0.512V36.571429z" p-id="106999" fill="#e0620d"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
1
frontend/public/images/colorSelector.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg t="1767367606621" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15611" width="200" height="200"><path d="M511.966509 0.066982c96.036384 0 185.886507 26.451603 262.724147 72.443261L767.949763 68.670494l-127.948963 221.638835A254.788666 254.788666 0 0 0 511.966509 256.050237V0.066982z" fill="#E70212" p-id="15612"></path><path d="M767.949763 68.670494a509.577332 509.577332 0 0 1 191.304819 194.120635L955.329506 256.050237l-221.638835 127.991627a257.263171 257.263171 0 0 0-93.689871-93.689871L767.949763 68.670494z" fill="#EA6101" p-id="15613"></path><path d="M955.329506 256.050237A509.577332 509.577332 0 0 1 1023.933018 519.798317V512.033491h-255.983255a254.788666 254.788666 0 0 0-34.259092-127.991627l221.638835-127.991627z" fill="#F39801" p-id="15614"></path><path d="M1023.933018 512.033491c0 90.020778-23.251812 174.665907-64.038478 248.175765l-4.565034 7.80749-221.638835-127.948964c21.758577-37.672202 34.259092-81.402675 34.259092-128.034291v-0.042664L1023.933018 512.033491z" fill="#FCC902" p-id="15615"></path><path d="M733.690671 640.025118l221.638835 127.991628a509.66266 509.66266 0 0 1-179.52959 182.900035l-7.850153 4.479707-127.991627-221.638835A257.263171 257.263171 0 0 0 733.690671 640.025118z" fill="#FEF200" p-id="15616"></path><path d="M640.0008 733.757653L767.949763 955.396488A509.66266 509.66266 0 0 1 521.011251 1024H511.966509v-255.983254a254.788666 254.788666 0 0 0 128.034291-34.259093z" fill="#90C320" p-id="15617"></path><path d="M511.966509 768.016746v255.983254c-90.020778 0-174.665907-23.251812-248.175765-64.038477L255.983254 955.396488l127.991628-221.638835c37.672202 21.758577 81.402675 34.259092 128.034291 34.259093z" fill="#019A44" p-id="15618"></path><path d="M383.974882 733.757653l-127.991628 221.638835a509.66266 509.66266 0 0 1-182.900035-179.529589L68.603512 768.016746l221.638835-127.991628A257.263171 257.263171 0 0 0 383.974882 733.757653z" fill="#019E97" p-id="15619"></path><path d="M255.983254 512.033491c0 46.631616 12.457852 90.362089 34.259093 128.034291L68.603512 768.016746A509.66266 509.66266 0 0 1 0 521.078233V512.033491h255.983254z" fill="#0169B8" p-id="15620"></path><path d="M68.603512 256.050237l221.638835 127.991627A254.788666 254.788666 0 0 0 255.983254 512.033491H0c0-90.020778 23.251812-174.665907 64.038477-248.175765L68.603512 256.050237z" fill="#1C2089" p-id="15621"></path><path d="M262.681483 64.745418L255.983254 68.670494l127.991628 221.638835A257.263171 257.263171 0 0 0 290.242347 384.041864L68.603512 256.050237a509.577332 509.577332 0 0 1 194.120635-191.304819z" fill="#621988" p-id="15622"></path><path d="M519.731334 0.066982H511.966509v255.983255a254.788666 254.788666 0 0 0-128.034291 34.259092L255.983254 68.670494A509.577332 509.577332 0 0 1 519.731334 0.066982z" fill="#910783" p-id="15623"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.8 KiB |
1
frontend/public/images/contextMenu.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg t="1767366808037" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="103196" width="200" height="200"><path d="M878.921143 96c27.099429 0 49.078857 21.942857 49.078857 49.078857v349.842286c0 27.099429-21.942857 49.078857-49.078857 49.078857h-221.842286c-27.099429 0-49.078857-21.942857-49.078857-49.078857V145.078857c0-27.099429 21.942857-49.078857 49.078857-49.078857z m-14.921143 320h-192v64h192v-64z m0-128h-192v64h192v-64z m0-128h-192v64h192v-64zM384 309.321143A202.678857 202.678857 0 0 1 586.678857 512v213.321143a202.678857 202.678857 0 0 1-202.678857 202.678857H298.678857a202.678857 202.678857 0 0 1-202.678857-202.678857V512a202.678857 202.678857 0 0 1 202.678857-202.678857z m138.642286 298.642286H160v117.394285a138.678857 138.678857 0 0 0 131.547429 138.459429l7.131428 0.182857H384a138.678857 138.678857 0 0 0 138.678857-138.678857l-0.036571-117.357714z m-213.321143-234.642286h-10.642286A138.678857 138.678857 0 0 0 160 512v31.963429h149.321143v-170.642286z" p-id="103197" fill="#8992c8"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
1
frontend/public/images/fold.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg t="1767366707029" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="100833" width="200" height="200"><path d="M533.333 54c16.138 0 29.75 12.016 31.753 28.03l17.828 142.569L896 224.6c17.496 0 31.713 14.042 31.996 31.47l0.004 0.53V939c0 17.673-14.327 32-32 32H469.735a31.94 31.94 0 0 1-3.051-0.102l-0.09-0.009c-10.834-0.868-19.434-6.86-24.45-14.999a31.766 31.766 0 0 1-3.374-7.39 32.348 32.348 0 0 1-1.405-7.246L419.752 800.4H128c-17.496 0-31.713-14.042-31.996-31.47L96 768.4V86c0-17.673 14.327-32 32-32zM864 288.599H590.917l13.33 106.6L704 395.2c17.673 0 32 14.327 32 32 0 17.496-14.042 31.713-31.47 31.996l-0.53 0.004-91.75-0.001 13.331 106.6L704 565.8c17.673 0 32 14.327 32 32 0 17.496-14.042 31.713-31.47 31.996l-0.53 0.004-70.416-0.001 16.548 132.332 0.287 2.298c0.024 0.188 0.046 0.376 0.066 0.565 0.986 9.171-2.002 17.793-7.523 24.232l-0.217 0.25L539.872 907H864v-618.4zM548.127 800.4H484.25l7.985 63.851 55.892-63.851zM505.085 118H160v618.4h287.598c0.302-0.004 0.603-0.004 0.904 0h133.913l-0.001-0.004L569.01 629.21l-3.386-27.076c-0.03-0.225-0.058-0.45-0.084-0.676l-21.256-169.977c-0.03-0.219-0.056-0.438-0.081-0.659L505.085 118zM448 565.8c17.673 0 32 14.327 32 32 0 17.496-14.042 31.713-31.47 31.996l-0.53 0.004H256c-17.673 0-32-14.327-32-32 0-17.496 14.042-31.713 31.47-31.996l0.53-0.004h192z m-21.333-170.6c17.673 0 32 14.327 32 32 0 17.496-14.042 31.713-31.471 31.996l-0.53 0.004H256c-17.673 0-32-14.327-32-32 0-17.496 14.042-31.713 31.47-31.996l0.53-0.004h170.667z m-21.334-170.6c17.673 0 32 14.327 32 32 0 17.496-14.041 31.713-31.47 31.996l-0.53 0.004H256c-17.673 0-32-14.327-32-32 0-17.496 14.042-31.713 31.47-31.996l0.53-0.004h149.333z" p-id="100834" fill="#1aaba8"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
1
frontend/public/images/highlightTrailingWhitespace.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg t="1767367226608" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5585" width="200" height="200"><path d="M416 64H768v64h-64v704h64v64H448v-64h64V512H416a224 224 0 1 1 0-448zM576 832h64V128H576v704zM416 128H512v320H416a160 160 0 0 1 0-320z" fill="#a4579d" p-id="5586"></path></svg>
|
||||||
|
After Width: | Height: | Size: 330 B |
1
frontend/public/images/highlightWhitespace.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1767366207284" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="95138" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M753.5 130.4v763.3h70.1v66.4H477v-66.4h70.1V547.1H443.9c-44.2 0-84.8-11.1-121.7-33.2-36.9-22.1-66.4-51.6-88.5-88.5s-33.2-76.8-33.2-119.8 11.1-83.6 33.2-121.7c22.1-38.1 51.6-67.6 88.5-88.5s77.4-31.3 121.7-31.3h379.8v66.4h-70.1z m-206.5 0H443.8c-49.2 0-90.3 17.2-123.5 51.6-33.2 34.4-49.8 75.6-49.8 123.5s16.6 88.5 49.8 121.7c33.2 33.2 74.4 49.8 123.5 49.8H547V130.4z m140.1 0H617v763.3h70.1V130.4z" p-id="95139"></path></svg>
|
||||||
|
After Width: | Height: | Size: 758 B |
1
frontend/public/images/httpClient.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1767365935803" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="81379" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M896 64a64 64 0 0 1 64 64v613.952l-121.28-95.68a83.2 83.2 0 0 0-110.848 7.04l-6.016 6.784-5.312 7.616a83.2 83.2 0 0 0-12.032 34.56l-0.064 1.728H595.2A83.2 83.2 0 0 0 512 787.2v44.8H128a64 64 0 0 1-64-64V128a64 64 0 0 1 64-64h768z" fill="#B5E3CC" p-id="81380"></path><path d="M640 256a32 32 0 1 1 0 64h-32v224a32 32 0 0 1-64 0V320h-64v224a32 32 0 0 1-64 0V320H384a32 32 0 0 1 0-64h256z m160 0a96 96 0 0 1 0 192H768v96a32 32 0 0 1-26.24 31.488L736 576a32 32 0 0 1-32-32v-256a32 32 0 0 1 32-32h64zM768 384h32a32 32 0 1 0 0-64H768v64zM288 256a32 32 0 0 1 32 32v256a32 32 0 0 1-64 0V448H192v96a32 32 0 0 1-64 0v-256a32 32 0 0 1 64 0V384h64V288a32 32 0 0 1 32-32zM772.096 699.712a19.2 19.2 0 0 0-4.096 11.904v56.32L595.2 768a19.2 19.2 0 0 0-19.2 19.2v89.6a19.2 19.2 0 0 0 19.2 19.2H768v56.384a19.2 19.2 0 0 0 31.104 15.104l152.576-120.384a19.2 19.2 0 0 0 0-30.208l-152.576-120.32a19.2 19.2 0 0 0-27.008 3.136z" fill="#129250" p-id="81381"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
1
frontend/public/images/hyperlink.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1767365120766" class="icon" viewBox="0 0 1160 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12589" xmlns:xlink="http://www.w3.org/1999/xlink" width="226.5625" height="200"><path d="M398.5408 736.142222l435.768889-384.568889a44.009244 44.009244 0 0 0 0-67.675022 59.483022 59.483022 0 0 0-76.731733 0l-435.768889 384.568889a43.872711 43.872711 0 0 0 0 67.675022 59.164444 59.164444 0 0 0 76.731733 0z m143.7696-66.582755a39.867733 39.867733 0 0 1 9.102222 25.031111 38.866489 38.866489 0 0 1-13.653333 30.128355L308.929422 926.151111a52.8384 52.8384 0 0 1-68.266666 0L111.047111 811.781689a39.139556 39.139556 0 0 1 0-60.302222l228.192711-201.9328a50.335289 50.335289 0 0 1 34.178845-11.969423 53.748622 53.748622 0 0 1 22.755555 4.551112l69.632-60.848356c-57.617067-41.824711-141.7216-38.365867-194.696533 7.964444L42.052267 690.631111c-56.069689 50.3808-56.069689 131.117511 0 181.4528l130.207289 114.323911a158.651733 158.651733 0 0 0 204.8 0L605.297778 785.066667c54.613333-48.196267 57.025422-125.474133 5.779911-176.355556zM1117.980444 151.916089L988.410311 37.546667c-56.797867-50.062222-148.821333-50.062222-205.664711 0L554.552889 238.933333c-52.519822 46.739911-56.388267 120.968533-9.102222 171.804445L614.4 349.889422a41.688178 41.688178 0 0 1-5.142756-20.48 38.866489 38.866489 0 0 1 13.653334-30.128355l228.875378-201.386667a50.335289 50.335289 0 0 1 34.178844-12.515556 52.383289 52.383289 0 0 1 34.178844 12.515556l129.570134 114.323911a39.139556 39.139556 0 0 1 0 60.302222l-228.192711 201.9328a50.335289 50.335289 0 0 1-34.178845 11.969423 57.7536 57.7536 0 0 1-28.353422-7.418312l-68.266667 60.302223c57.389511 45.101511 144.543289 43.099022 199.202134-4.551111l228.192711-201.9328a117.418667 117.418667 0 0 0 0-180.906667z" fill="#1A97F0" p-id="12590"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
1
frontend/public/images/lineNumbers.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg t="1767366749042" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="102155" width="200" height="200"><path d="M426.7008 256c0-23.552 19.0976-42.6496 42.6496-42.6496h384a42.6496 42.6496 0 1 1 0 85.2992h-384A42.6496 42.6496 0 0 1 426.7008 256zM426.7008 512c0-23.552 19.0976-42.6496 42.6496-42.6496h384a42.6496 42.6496 0 1 1 0 85.2992h-384A42.6496 42.6496 0 0 1 426.7008 512zM469.2992 768c0-23.552 19.1488-42.6496 42.7008-42.6496h341.2992a42.6496 42.6496 0 0 1 0 85.2992H512A42.6496 42.6496 0 0 1 469.2992 768zM256 640a42.6496 42.6496 0 0 0-42.6496 42.6496 42.6496 42.6496 0 0 1-85.3504 0 128 128 0 1 1 256 0c0 25.856-11.264 45.6192-22.4256 59.8528-8.0384 10.1888-18.5856 20.48-26.8288 28.5184l-5.888 5.8368a42.4448 42.4448 0 0 1-2.8672 2.56l-37.4784 31.232h52.8384a42.6496 42.6496 0 1 1 0 85.3504H170.6496a42.6496 42.6496 0 0 1-27.2896-75.4688l126.5152-105.472 6.5024-6.3488 0.4096-0.4096 7.2704-7.168c4.608-4.608 7.936-8.192 10.3936-11.3664a28.672 28.672 0 0 0 3.9424-6.0928c0.3072-0.7168 0.256-0.9728 0.256-1.024A42.6496 42.6496 0 0 0 256 640zM272.3328 131.2256a42.6496 42.6496 0 0 1 26.3168 39.424v256a42.6496 42.6496 0 0 1-85.2992 0V273.664l-12.4928 12.4928a42.6496 42.6496 0 1 1-60.3648-60.3136l85.3504-85.3504a42.6496 42.6496 0 0 1 46.4896-9.216z" p-id="102156" fill="#87c38f"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
1
frontend/public/images/markdown.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1767365625477" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="51837" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M98.649225 16.619164h734.636904v990.162784h-734.636904z" fill="#FF8A90" p-id="51838"></path><path d="M881.197231 128.411736h-31.940735V32.589531c0-17.642265-14.29847-31.940735-31.940735-31.940735H114.619592c-17.642265 0-31.940735 14.29847-31.940735 31.940735v958.222049c0 17.642265 14.29847 31.940735 31.940735 31.940735h702.696169c17.642265 0 31.940735-14.29847 31.940735-31.940735V415.878351h31.940735c17.642265 0 31.940735-14.29847 31.940735-31.940735V160.352471c0-17.642265-14.29847-31.940735-31.940735-31.940735z m-63.88147 0h-383.288819c-17.642265 0-31.940735 14.29847-31.940735 31.940735V383.937616c0 17.642265 14.29847 31.940735 31.940735 31.940735h383.288819v574.933229H114.619592v-958.222049h702.696169v95.822205z" fill="#2B3139" p-id="51839"></path><path d="M434.026942 160.352471h447.170289V383.937616h-447.170289z" fill="#FFFFFF" p-id="51840"></path><path d="M544.808889 215.175748h49.969783l16.294765 67.025636h0.311922l16.294765-67.025636h49.957306v113.963544h-33.18842v-73.101861h-0.336875l-19.80076 73.101861h-26.176431l-19.788283-73.101861h-0.336875v73.101861h-33.200897zM698.947889 215.175748h57.618092c37.992007 0 51.392143 28.097865 51.392143 56.819573 0 34.947656-18.490691 57.143971-58.241934 57.143971h-50.768301v-113.963544z" fill="#2B3139" p-id="51841"></path><path d="M726.584111 299.918511h13.712058c21.85944 0 25.065991-17.717126 25.065991-28.409787 0-7.174189-2.233356-27.112194-27.611269-27.112194h-11.154303v55.521981z" fill="#FFFFFF" p-id="51842"></path><path d="M630.512369 785.841895l-94.998733-129.709328h57.318647V544.888976h76.445658v111.243591h57.30617L630.487415 785.841895z" fill="#1EB9B0" p-id="51843"></path><path d="M508.139428 785.754557l-76.445657 0.087338v-120.439029l-57.331124 77.194268-57.343601-77.194268v120.439029H240.573389V544.976313h76.445657l57.343601 80.288528 57.331124-80.288528 76.445657-0.087337z" fill="#1EB9B0" p-id="51844"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
1
frontend/public/images/minimap.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg t="1767367796950" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="18541" width="200" height="200"><path d="M880.489336 512H993.882278v455.107765A56.786824 56.786824 0 0 1 937.185807 1024h-56.681412V512z" fill="#4AC3BB" fill-opacity=".603" p-id="18542"></path><path d="M143.510513 1024a113.182118 113.182118 0 0 1-80.188235-33.325176A113.980235 113.980235 0 0 1 30.117572 910.215529V113.784471C30.117572 83.606588 42.059219 54.663529 63.322278 33.325176A113.182118 113.182118 0 0 1 143.510513 0h510.238118C778.977807 0 880.489336 101.872941 880.489336 227.553882v739.553883A56.786824 56.786824 0 0 0 937.185807 1024H143.510513z" fill="#4AC3BB" p-id="18543"></path><path d="M575.653572 335.329882c64.331294 65.024 66.529882 169.758118 4.954353 237.477647l-4.954353 5.240471-98.063059 122.473412a28.175059 28.175059 0 0 1-21.985882 10.586353 28.175059 28.175059 0 0 1-21.985883-10.586353l-98.078117-122.473412-4.412236-4.638118c-63.503059-68.487529-60.777412-175.841882 6.098824-240.941176a168.478118 168.478118 0 0 1 238.426353 2.861176z m-120.048941 64.150589a56.470588 56.470588 0 0 0-49.016471 28.611764 57.735529 57.735529 0 0 0 0 57.193412 56.470588 56.470588 0 0 0 49.016471 28.611765c31.247059-0.015059 56.576-25.630118 56.576-57.22353 0-31.578353-25.328941-57.193412-56.576-57.193411z" fill="#FFFFFF" fill-opacity=".95" p-id="18544"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
1
frontend/public/images/rainbowBrackets.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1767364585914" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8006" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M960 128c0-35.36-28.704-64.224-63.936-61.728A896.48 896.48 0 0 0 326.4 326.4a896.48 896.48 0 0 0-260.128 569.664C63.776 931.296 92.64 960 128 960c0 0 19.52 0.576 32 0 64-272 84.48-383.68 234.24-533.76C544.32 276.16 752 192 960 160V128z" fill="#F8312F" p-id="8007"></path><path d="M960 256V160a800 800 0 0 0-565.76 234.24A801.344 801.344 0 0 0 160 960h96c32-128 106.24-333.76 238.08-465.92C625.92 362.24 752 304 960 256z" fill="#FFB02E" p-id="8008"></path><path d="M960 256v96c-160 16-284.16 96-398.08 209.92C448 676.16 384 800 352 960H256c0-186.56 74.24-365.76 206.08-497.92A704.32 704.32 0 0 1 960 256z" fill="#FFF478" p-id="8009"></path><path d="M630.08 630.08C534.08 726.08 480 832 448 960h-96c0-161.28 64-315.84 177.92-430.08C643.84 416 798.72 352 960 352v96c-144 32-233.92 86.08-329.92 182.08z" fill="#00D26A" p-id="8010"></path><path d="M960 544v-96c-135.68 0-265.92 54.08-361.92 150.08-96 96-150.08 226.24-150.08 361.92h96c0-110.4 43.84-216.32 121.92-294.08C744 587.84 849.92 544 960 544z" fill="#3F5FFF" p-id="8011"></path><path d="M960 576c0 35.36-28.928 63.36-63.584 70.336a320.384 320.384 0 0 0-250.112 250.08C639.36 931.04 611.392 960 576 960h-32c0-110.4 43.84-216.32 121.92-294.08C744 587.84 849.92 544 960 544v32z" fill="#8D65C5" p-id="8012"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
1
frontend/public/images/search.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg t="1767366992790" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="111373" width="200" height="200"><path d="M581.973333 846.933333a380.8 380.8 0 1 1 380.8-380.8A381.226667 381.226667 0 0 1 581.973333 846.933333z m0-688a307.2 307.2 0 1 0 307.2 307.2 307.413333 307.413333 0 0 0-307.2-307.2z" fill="#FA6302" p-id="111374"></path><path d="M146.56 938.666667a36.906667 36.906667 0 0 1-26.026667-64l192-190.933334a36.906667 36.906667 0 0 1 52.053334 52.266667l-192 192a37.333333 37.333333 0 0 1-26.026667 10.666667z" fill="#43D7B4" p-id="111375"></path><path d="M470.826667 274.773333m-49.066667 0a49.066667 49.066667 0 1 0 98.133333 0 49.066667 49.066667 0 1 0-98.133333 0Z" fill="#43D7B4" p-id="111376"></path><path d="M312.106667 684.8l-23.68 23.466667A388.693333 388.693333 0 0 0 341.333333 760.32l23.466667-23.253333a36.906667 36.906667 0 0 0-52.053333-52.266667z" fill="#425300" p-id="111377"></path></svg>
|
||||||
|
After Width: | Height: | Size: 956 B |
1
frontend/public/images/translator.svg
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
1
frontend/src/assets/images/translator.svg
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
@@ -24,6 +24,7 @@ export const CONFIG_KEY_MAP = {
|
|||||||
enableWindowSnap: 'general.enableWindowSnap',
|
enableWindowSnap: 'general.enableWindowSnap',
|
||||||
enableLoadingAnimation: 'general.enableLoadingAnimation',
|
enableLoadingAnimation: 'general.enableLoadingAnimation',
|
||||||
enableTabs: 'general.enableTabs',
|
enableTabs: 'general.enableTabs',
|
||||||
|
enableMemoryMonitor: 'general.enableMemoryMonitor',
|
||||||
// editing
|
// editing
|
||||||
fontSize: 'editing.fontSize',
|
fontSize: 'editing.fontSize',
|
||||||
fontFamily: 'editing.fontFamily',
|
fontFamily: 'editing.fontFamily',
|
||||||
@@ -88,6 +89,7 @@ export const DEFAULT_CONFIG: AppConfig = {
|
|||||||
enableWindowSnap: true,
|
enableWindowSnap: true,
|
||||||
enableLoadingAnimation: true,
|
enableLoadingAnimation: true,
|
||||||
enableTabs: false,
|
enableTabs: false,
|
||||||
|
enableMemoryMonitor: true,
|
||||||
},
|
},
|
||||||
editing: {
|
editing: {
|
||||||
fontSize: CONFIG_LIMITS.fontSize.default,
|
fontSize: CONFIG_LIMITS.fontSize.default,
|
||||||
|
|||||||
105
frontend/src/components/accordion/AccordionContainer.vue
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { provide, ref } from 'vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/**
|
||||||
|
* 是否允许多个面板同时展开
|
||||||
|
* @default false - 单选模式(手风琴效果)
|
||||||
|
*/
|
||||||
|
multiple?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
multiple: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 当前展开的项(单选模式)或展开项列表(多选模式)
|
||||||
|
const expandedItems = ref<Set<string | number>>(new Set());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换展开状态
|
||||||
|
*/
|
||||||
|
const toggleItem = (id: string | number) => {
|
||||||
|
if (props.multiple) {
|
||||||
|
// 多选模式:切换单个项
|
||||||
|
if (expandedItems.value.has(id)) {
|
||||||
|
expandedItems.value.delete(id);
|
||||||
|
} else {
|
||||||
|
expandedItems.value.add(id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 单选模式:只能展开一个
|
||||||
|
if (expandedItems.value.has(id)) {
|
||||||
|
expandedItems.value.clear();
|
||||||
|
} else {
|
||||||
|
expandedItems.value.clear();
|
||||||
|
expandedItems.value.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 触发响应式更新
|
||||||
|
expandedItems.value = new Set(expandedItems.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查项是否展开
|
||||||
|
*/
|
||||||
|
const isExpanded = (id: string | number): boolean => {
|
||||||
|
return expandedItems.value.has(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展开指定项
|
||||||
|
*/
|
||||||
|
const expand = (id: string | number) => {
|
||||||
|
if (!props.multiple) {
|
||||||
|
expandedItems.value.clear();
|
||||||
|
}
|
||||||
|
expandedItems.value.add(id);
|
||||||
|
expandedItems.value = new Set(expandedItems.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收起指定项
|
||||||
|
*/
|
||||||
|
const collapse = (id: string | number) => {
|
||||||
|
expandedItems.value.delete(id);
|
||||||
|
expandedItems.value = new Set(expandedItems.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收起所有项
|
||||||
|
*/
|
||||||
|
const collapseAll = () => {
|
||||||
|
expandedItems.value.clear();
|
||||||
|
expandedItems.value = new Set(expandedItems.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 通过 provide 向子组件提供状态和方法
|
||||||
|
provide('accordion', {
|
||||||
|
toggleItem,
|
||||||
|
isExpanded,
|
||||||
|
expand,
|
||||||
|
collapse,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 暴露方法供父组件使用
|
||||||
|
defineExpose({
|
||||||
|
expand,
|
||||||
|
collapse,
|
||||||
|
collapseAll,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="accordion-container">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.accordion-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
187
frontend/src/components/accordion/AccordionItem.vue
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { inject, computed, ref } from 'vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/**
|
||||||
|
* 唯一标识符
|
||||||
|
*/
|
||||||
|
id: string | number;
|
||||||
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
|
title?: string;
|
||||||
|
/**
|
||||||
|
* 是否禁用
|
||||||
|
*/
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const accordion = inject<{
|
||||||
|
toggleItem: (id: string | number) => void;
|
||||||
|
isExpanded: (id: string | number) => boolean;
|
||||||
|
}>('accordion');
|
||||||
|
|
||||||
|
if (!accordion) {
|
||||||
|
throw new Error('AccordionItem must be used within AccordionContainer');
|
||||||
|
}
|
||||||
|
|
||||||
|
const isExpanded = computed(() => accordion.isExpanded(props.id));
|
||||||
|
|
||||||
|
const toggle = () => {
|
||||||
|
if (!props.disabled) {
|
||||||
|
accordion.toggleItem(props.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 内容容器的引用,用于计算高度
|
||||||
|
const contentRef = ref<HTMLElement>();
|
||||||
|
const contentHeight = computed(() => {
|
||||||
|
if (!contentRef.value) return '0px';
|
||||||
|
return isExpanded.value ? `${contentRef.value.scrollHeight}px` : '0px';
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="accordion-item"
|
||||||
|
:class="{
|
||||||
|
'is-expanded': isExpanded,
|
||||||
|
'is-disabled': disabled
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<!-- 标题栏 -->
|
||||||
|
<div
|
||||||
|
class="accordion-header"
|
||||||
|
@click="toggle"
|
||||||
|
:aria-expanded="isExpanded"
|
||||||
|
:aria-disabled="disabled"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
@keydown.enter="toggle"
|
||||||
|
@keydown.space.prevent="toggle"
|
||||||
|
>
|
||||||
|
<div class="accordion-title">
|
||||||
|
<slot name="title">
|
||||||
|
{{ title }}
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<div class="accordion-icon">
|
||||||
|
<svg
|
||||||
|
width="12"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 12 12"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3 4.5L6 7.5L9 4.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 内容区域 -->
|
||||||
|
<div
|
||||||
|
class="accordion-content-wrapper"
|
||||||
|
:style="{ height: contentHeight }"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
ref="contentRef"
|
||||||
|
class="accordion-content"
|
||||||
|
>
|
||||||
|
<div class="accordion-content-inner">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.accordion-item {
|
||||||
|
border-bottom: 1px solid var(--settings-border);
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-expanded {
|
||||||
|
background-color: var(--settings-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
.accordion-header {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 12px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
|
||||||
|
&:hover:not([aria-disabled="true"]) {
|
||||||
|
background-color: var(--settings-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid #4a9eff;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-title {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--settings-text);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
|
||||||
|
.is-expanded & {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-content-wrapper {
|
||||||
|
overflow: hidden;
|
||||||
|
transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-content {
|
||||||
|
// 用于测量实际内容高度
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-content-inner {
|
||||||
|
padding: 0 16px 12px 16px;
|
||||||
|
color: var(--settings-text);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
3
frontend/src/components/accordion/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export { default as AccordionContainer } from './AccordionContainer.vue';
|
||||||
|
export { default as AccordionItem } from './AccordionItem.vue';
|
||||||
|
|
||||||
@@ -1,5 +1,14 @@
|
|||||||
export default {
|
export default {
|
||||||
locale: 'en-US',
|
locale: 'en-US',
|
||||||
|
common: {
|
||||||
|
ok: 'OK',
|
||||||
|
cancel: 'Cancel',
|
||||||
|
edit: 'Edit',
|
||||||
|
delete: 'Delete',
|
||||||
|
confirm: 'Confirm',
|
||||||
|
save: 'Save',
|
||||||
|
reset: 'Reset'
|
||||||
|
},
|
||||||
titlebar: {
|
titlebar: {
|
||||||
minimize: 'Minimize',
|
minimize: 'Minimize',
|
||||||
maximize: 'Maximize',
|
maximize: 'Maximize',
|
||||||
@@ -56,6 +65,19 @@ export default {
|
|||||||
},
|
},
|
||||||
resetToDefault: 'Reset to Default',
|
resetToDefault: 'Reset to Default',
|
||||||
confirmReset: 'Confirm Reset?',
|
confirmReset: 'Confirm Reset?',
|
||||||
|
noKeybinding: 'Not Set',
|
||||||
|
waitingForKey: 'Waiting...',
|
||||||
|
clickToSet: 'Click to set keybinding',
|
||||||
|
editKeybinding: 'Edit keybinding',
|
||||||
|
config: {
|
||||||
|
enabled: 'Enabled',
|
||||||
|
preventDefault: 'Prevent Default',
|
||||||
|
keybinding: 'Keybinding'
|
||||||
|
},
|
||||||
|
keyPlaceholder: 'Enter key, press Enter to add',
|
||||||
|
invalidFormat: 'Invalid format',
|
||||||
|
conflict: 'Conflict: {command}',
|
||||||
|
maxKeysReached: 'Maximum 4 keys allowed',
|
||||||
commands: {
|
commands: {
|
||||||
showSearch: 'Show search panel',
|
showSearch: 'Show search panel',
|
||||||
hideSearch: 'Hide search panel',
|
hideSearch: 'Hide search panel',
|
||||||
@@ -178,6 +200,7 @@ export default {
|
|||||||
enableWindowSnap: 'Enable Window Snapping',
|
enableWindowSnap: 'Enable Window Snapping',
|
||||||
enableLoadingAnimation: 'Enable Loading Animation',
|
enableLoadingAnimation: 'Enable Loading Animation',
|
||||||
enableTabs: 'Enable Tabs',
|
enableTabs: 'Enable Tabs',
|
||||||
|
enableMemoryMonitor: 'Enable Memory Monitor',
|
||||||
startup: 'Startup Settings',
|
startup: 'Startup Settings',
|
||||||
startAtLogin: 'Start at Login',
|
startAtLogin: 'Start at Login',
|
||||||
dataStorage: 'Data Storage',
|
dataStorage: 'Data Storage',
|
||||||
@@ -223,6 +246,7 @@ export default {
|
|||||||
categoryEditing: 'Editing Enhancement',
|
categoryEditing: 'Editing Enhancement',
|
||||||
categoryUI: 'UI Enhancement',
|
categoryUI: 'UI Enhancement',
|
||||||
categoryTools: 'Tools',
|
categoryTools: 'Tools',
|
||||||
|
enabled: 'Enabled',
|
||||||
configuration: 'Configuration',
|
configuration: 'Configuration',
|
||||||
resetToDefault: 'Reset to Default Configuration',
|
resetToDefault: 'Reset to Default Configuration',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
export default {
|
export default {
|
||||||
locale: 'zh-CN',
|
locale: 'zh-CN',
|
||||||
|
common: {
|
||||||
|
ok: '确定',
|
||||||
|
cancel: '取消',
|
||||||
|
edit: '编辑',
|
||||||
|
delete: '删除',
|
||||||
|
confirm: '确认',
|
||||||
|
save: '保存',
|
||||||
|
reset: '重置'
|
||||||
|
},
|
||||||
titlebar: {
|
titlebar: {
|
||||||
minimize: '最小化',
|
minimize: '最小化',
|
||||||
maximize: '最大化',
|
maximize: '最大化',
|
||||||
@@ -56,6 +65,19 @@ export default {
|
|||||||
},
|
},
|
||||||
resetToDefault: '重置为默认',
|
resetToDefault: '重置为默认',
|
||||||
confirmReset: '确认重置?',
|
confirmReset: '确认重置?',
|
||||||
|
noKeybinding: '未设置',
|
||||||
|
waitingForKey: '等待输入...',
|
||||||
|
clickToSet: '点击设置快捷键',
|
||||||
|
editKeybinding: '编辑快捷键',
|
||||||
|
config: {
|
||||||
|
enabled: '启用',
|
||||||
|
preventDefault: '阻止默认',
|
||||||
|
keybinding: '快捷键'
|
||||||
|
},
|
||||||
|
keyPlaceholder: '输入键名, 回车添加',
|
||||||
|
invalidFormat: '格式错误',
|
||||||
|
conflict: '冲突: {command}',
|
||||||
|
maxKeysReached: '最多只能添加4个键',
|
||||||
commands: {
|
commands: {
|
||||||
showSearch: '显示搜索面板',
|
showSearch: '显示搜索面板',
|
||||||
hideSearch: '隐藏搜索面板',
|
hideSearch: '隐藏搜索面板',
|
||||||
@@ -179,6 +201,7 @@ export default {
|
|||||||
enableWindowSnap: '启用窗口吸附',
|
enableWindowSnap: '启用窗口吸附',
|
||||||
enableLoadingAnimation: '启用加载动画',
|
enableLoadingAnimation: '启用加载动画',
|
||||||
enableTabs: '启用标签页',
|
enableTabs: '启用标签页',
|
||||||
|
enableMemoryMonitor: '启用内存监视器',
|
||||||
startup: '启动设置',
|
startup: '启动设置',
|
||||||
startAtLogin: '开机自启动',
|
startAtLogin: '开机自启动',
|
||||||
dataStorage: '数据存储',
|
dataStorage: '数据存储',
|
||||||
@@ -226,6 +249,7 @@ export default {
|
|||||||
categoryEditing: '编辑增强',
|
categoryEditing: '编辑增强',
|
||||||
categoryUI: '界面增强',
|
categoryUI: '界面增强',
|
||||||
categoryTools: '工具扩展',
|
categoryTools: '工具扩展',
|
||||||
|
enabled: '启用',
|
||||||
configuration: '配置',
|
configuration: '配置',
|
||||||
resetToDefault: '重置为默认配置',
|
resetToDefault: '重置为默认配置',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -233,6 +233,9 @@ export const useConfigStore = defineStore('config', () => {
|
|||||||
// 标签页配置相关方法
|
// 标签页配置相关方法
|
||||||
setEnableTabs: (value: boolean) => updateConfig('enableTabs', value),
|
setEnableTabs: (value: boolean) => updateConfig('enableTabs', value),
|
||||||
|
|
||||||
|
// 内存监视器配置相关方法
|
||||||
|
setEnableMemoryMonitor: (value: boolean) => updateConfig('enableMemoryMonitor', value),
|
||||||
|
|
||||||
// 快捷键模式配置相关方法
|
// 快捷键模式配置相关方法
|
||||||
setKeymapMode: (value: any) => updateConfig('keymapMode', value),
|
setKeymapMode: (value: any) => updateConfig('keymapMode', value),
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ export interface CodeBlockOptions {
|
|||||||
|
|
||||||
/** 新建块时的默认语言 */
|
/** 新建块时的默认语言 */
|
||||||
defaultLanguage?: SupportedLanguage;
|
defaultLanguage?: SupportedLanguage;
|
||||||
|
|
||||||
|
/** 分隔符高度(像素) */
|
||||||
|
separatorHeight?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,6 +89,7 @@ export function createCodeBlockExtension(options: CodeBlockOptions = {}): Extens
|
|||||||
showBackground = true,
|
showBackground = true,
|
||||||
enableAutoDetection = true,
|
enableAutoDetection = true,
|
||||||
defaultLanguage = 'text',
|
defaultLanguage = 'text',
|
||||||
|
separatorHeight = 12,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -104,7 +108,8 @@ export function createCodeBlockExtension(options: CodeBlockOptions = {}): Extens
|
|||||||
|
|
||||||
// 视觉装饰系统
|
// 视觉装饰系统
|
||||||
...getBlockDecorationExtensions({
|
...getBlockDecorationExtensions({
|
||||||
showBackground
|
showBackground,
|
||||||
|
separatorHeight
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 光标保护(防止方向键移动到分隔符上)
|
// 光标保护(防止方向键移动到分隔符上)
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { ref } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useRouter, useRoute } from 'vue-router';
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
|
import { useConfigStore } from '@/stores/configStore';
|
||||||
import MemoryMonitor from '@/components/monitor/MemoryMonitor.vue';
|
import MemoryMonitor from '@/components/monitor/MemoryMonitor.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const configStore = useConfigStore();
|
||||||
|
|
||||||
|
// 计算属性
|
||||||
|
const enableMemoryMonitor = computed(() => configStore.config.general.enableMemoryMonitor);
|
||||||
|
|
||||||
// 导航配置
|
// 导航配置
|
||||||
const navItems = [
|
const navItems = [
|
||||||
@@ -64,7 +69,7 @@ const goBackToEditor = async () => {
|
|||||||
<span class="nav-text">{{ item.id === 'test' ? 'Test' : t(`settings.${item.id}`) }}</span>
|
<span class="nav-text">{{ item.id === 'test' ? 'Test' : t(`settings.${item.id}`) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-footer">
|
<div class="settings-footer" v-if="enableMemoryMonitor">
|
||||||
<div class="memory-info-section">
|
<div class="memory-info-section">
|
||||||
<div class="section-title">{{ t('settings.systemInfo') }}</div>
|
<div class="section-title">{{ t('settings.systemInfo') }}</div>
|
||||||
<MemoryMonitor />
|
<MemoryMonitor />
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import {
|
|||||||
} from '@/views/editor/manager/extensions';
|
} from '@/views/editor/manager/extensions';
|
||||||
import {getExtensionManager} from '@/views/editor/manager';
|
import {getExtensionManager} from '@/views/editor/manager';
|
||||||
import SettingSection from '../components/SettingSection.vue';
|
import SettingSection from '../components/SettingSection.vue';
|
||||||
import SettingItem from '../components/SettingItem.vue';
|
import AccordionContainer from '@/components/accordion/AccordionContainer.vue';
|
||||||
|
import AccordionItem from '@/components/accordion/AccordionItem.vue';
|
||||||
import ToggleSwitch from '../components/ToggleSwitch.vue';
|
import ToggleSwitch from '../components/ToggleSwitch.vue';
|
||||||
|
|
||||||
const {t} = useI18n();
|
const {t} = useI18n();
|
||||||
@@ -27,11 +28,11 @@ onMounted(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 展开状态管理
|
// 展开状态管理
|
||||||
const expandedExtensions = ref<Set<number>>(new Set());
|
const expandedExtensions = ref<number[]>([]);
|
||||||
|
|
||||||
// 获取所有可用的扩展
|
// 获取所有可用的扩展
|
||||||
const availableExtensions = computed(() => {
|
const availableExtensions = computed(() => {
|
||||||
return getExtensionsMap().map(name => {
|
const extensions = getExtensionsMap().map(name => {
|
||||||
const extension = extensionStore.extensions.find(ext => ext.name === name);
|
const extension = extensionStore.extensions.find(ext => ext.name === name);
|
||||||
return {
|
return {
|
||||||
id: extension?.id ?? 0,
|
id: extension?.id ?? 0,
|
||||||
@@ -44,15 +45,13 @@ const availableExtensions = computed(() => {
|
|||||||
defaultConfig: getExtensionDefaultConfig(name)
|
defaultConfig: getExtensionDefaultConfig(name)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
console.log('Available Extensions:', extensions);
|
||||||
|
return extensions;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 切换展开状态
|
// 获取扩展图标路径(直接使用扩展名称作为文件名)
|
||||||
const toggleExpanded = (extensionId: number) => {
|
const getExtensionIcon = (name: string): string => {
|
||||||
if (expandedExtensions.value.has(extensionId)) {
|
return `/images/${name}.svg`;
|
||||||
expandedExtensions.value.delete(extensionId);
|
|
||||||
} else {
|
|
||||||
expandedExtensions.value.add(extensionId);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新扩展状态
|
// 更新扩展状态
|
||||||
@@ -193,152 +192,227 @@ const handleConfigInput = async (
|
|||||||
<template>
|
<template>
|
||||||
<div class="settings-page">
|
<div class="settings-page">
|
||||||
<SettingSection :title="t('settings.extensions')">
|
<SettingSection :title="t('settings.extensions')">
|
||||||
<div
|
<!-- 空状态提示 -->
|
||||||
v-for="extension in availableExtensions"
|
<div v-if="availableExtensions.length === 0" class="empty-state">
|
||||||
:key="extension.name"
|
<p>{{ t('settings.extensionsPage.loading') }}</p>
|
||||||
class="extension-item"
|
|
||||||
>
|
|
||||||
<!-- 扩展主项 -->
|
|
||||||
<SettingItem
|
|
||||||
:title="extension.displayName"
|
|
||||||
:description="extension.description"
|
|
||||||
>
|
|
||||||
<div class="extension-controls">
|
|
||||||
<button
|
|
||||||
v-if="extension.hasConfig"
|
|
||||||
class="config-button"
|
|
||||||
@click="toggleExpanded(extension.id)"
|
|
||||||
:class="{ expanded: expandedExtensions.has(extension.id) }"
|
|
||||||
:title="t('settings.extensionsPage.configuration')"
|
|
||||||
>
|
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
||||||
stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<path
|
|
||||||
d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/>
|
|
||||||
<circle cx="12" cy="12" r="3"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div v-else class="config-placeholder"></div>
|
|
||||||
<ToggleSwitch
|
|
||||||
:model-value="extension.enabled"
|
|
||||||
@update:model-value="updateExtension(extension.id, $event)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</SettingItem>
|
|
||||||
|
|
||||||
<!-- 可展开的配置区域 -->
|
|
||||||
<div
|
|
||||||
v-if="extension.hasConfig && expandedExtensions.has(extension.id)"
|
|
||||||
class="extension-config"
|
|
||||||
>
|
|
||||||
<!-- 配置项标题和重置按钮 -->
|
|
||||||
<div class="config-header">
|
|
||||||
<h4 class="config-title">{{ t('settings.extensionsPage.configuration') }}</h4>
|
|
||||||
<button
|
|
||||||
class="reset-button"
|
|
||||||
@click="resetExtension(extension.id)"
|
|
||||||
:title="t('settings.extensionsPage.resetToDefault')"
|
|
||||||
>
|
|
||||||
{{ t('settings.reset') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="config-table-wrapper">
|
|
||||||
<table class="config-table">
|
|
||||||
<tbody>
|
|
||||||
<tr
|
|
||||||
v-for="[configKey, configValue] in Object.entries(extension.defaultConfig)"
|
|
||||||
:key="configKey"
|
|
||||||
>
|
|
||||||
<th scope="row" class="config-table-key">
|
|
||||||
{{ configKey }}
|
|
||||||
</th>
|
|
||||||
<td class="config-table-value">
|
|
||||||
<input
|
|
||||||
class="config-value-input"
|
|
||||||
type="text"
|
|
||||||
:value="formatConfigValue(getConfigValue(extension.config, configKey, configValue))"
|
|
||||||
@change="handleConfigInput(extension.id, configKey, configValue, $event)"
|
|
||||||
@keyup.enter.prevent="handleConfigInput(extension.id, configKey, configValue, $event)"
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 扩展列表 -->
|
||||||
|
<AccordionContainer v-else v-model="expandedExtensions" :multiple="false">
|
||||||
|
<AccordionItem
|
||||||
|
v-for="extension in availableExtensions"
|
||||||
|
:key="extension.id"
|
||||||
|
:id="extension.id"
|
||||||
|
:class="{ 'extension-disabled': !extension.enabled }"
|
||||||
|
>
|
||||||
|
<!-- 标题插槽:显示图标和扩展名称 -->
|
||||||
|
<template #title>
|
||||||
|
<div class="extension-header">
|
||||||
|
<div class="extension-icon-wrapper">
|
||||||
|
<div class="extension-icon-placeholder" :class="{ 'disabled': !extension.enabled }">
|
||||||
|
<!-- 直接使用扩展名称作为图标文件名 -->
|
||||||
|
<img
|
||||||
|
:src="getExtensionIcon(extension.name)"
|
||||||
|
:alt="extension.displayName"
|
||||||
|
class="extension-icon-img"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="extension-info">
|
||||||
|
<div class="extension-name">{{ extension.displayName }}</div>
|
||||||
|
<div class="extension-description">{{ extension.description }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 默认插槽:显示开关和配置项 -->
|
||||||
|
<div class="extension-content">
|
||||||
|
<!-- 启用开关 -->
|
||||||
|
<div class="extension-toggle-section">
|
||||||
|
<label class="toggle-label">{{ t('settings.extensionsPage.enabled') }}</label>
|
||||||
|
<ToggleSwitch
|
||||||
|
:model-value="extension.enabled"
|
||||||
|
@update:model-value="updateExtension(extension.id, $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 配置项 -->
|
||||||
|
<div v-if="extension.hasConfig" class="extension-config-section">
|
||||||
|
<div class="config-header">
|
||||||
|
<h4 class="config-title">{{ t('settings.extensionsPage.configuration') }}</h4>
|
||||||
|
<button
|
||||||
|
class="reset-button"
|
||||||
|
@click="resetExtension(extension.id)"
|
||||||
|
:title="t('settings.extensionsPage.resetToDefault')"
|
||||||
|
>
|
||||||
|
{{ t('settings.reset') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="config-table-wrapper">
|
||||||
|
<table class="config-table">
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="[configKey, configValue] in Object.entries(extension.defaultConfig)"
|
||||||
|
:key="configKey"
|
||||||
|
>
|
||||||
|
<th scope="row" class="config-table-key">
|
||||||
|
{{ configKey }}
|
||||||
|
</th>
|
||||||
|
<td class="config-table-value">
|
||||||
|
<input
|
||||||
|
class="config-value-input"
|
||||||
|
type="text"
|
||||||
|
:value="formatConfigValue(getConfigValue(extension.config, configKey, configValue))"
|
||||||
|
@change="handleConfigInput(extension.id, configKey, configValue, $event)"
|
||||||
|
@keyup.enter.prevent="handleConfigInput(extension.id, configKey, configValue, $event)"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AccordionItem>
|
||||||
|
</AccordionContainer>
|
||||||
</SettingSection>
|
</SettingSection>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.extension-item {
|
.empty-state {
|
||||||
border-bottom: 1px solid var(--settings-input-border);
|
padding: 40px 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--settings-text-secondary);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
&:last-child {
|
// 禁用状态的扩展项
|
||||||
border-bottom: none;
|
:deep(.extension-disabled) {
|
||||||
|
background-color: rgba(0, 0, 0, 0.02);
|
||||||
|
|
||||||
|
.accordion-header {
|
||||||
|
opacity: 0.7;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.03);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-expanded {
|
||||||
|
background-color: rgba(0, 0, 0, 0.03);
|
||||||
|
|
||||||
|
.accordion-header {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.extension-description {
|
||||||
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-controls {
|
.extension-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
min-width: 140px;
|
width: 100%;
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-button {
|
.extension-icon-wrapper {
|
||||||
padding: 4px;
|
|
||||||
border: none;
|
|
||||||
background: none;
|
|
||||||
color: var(--settings-text-secondary);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
border-radius: 4px;
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 24px;
|
}
|
||||||
height: 24px;
|
|
||||||
|
.extension-icon-placeholder {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: linear-gradient(135deg, rgba(var(--settings-accent-rgb, 74, 158, 255), 0.12), rgba(var(--settings-accent-rgb, 74, 158, 255), 0.06));
|
||||||
|
border: 1px solid rgba(var(--settings-accent-rgb, 74, 158, 255), 0.15);
|
||||||
|
color: white;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
&:hover {
|
&.disabled {
|
||||||
background-color: var(--settings-hover);
|
background: linear-gradient(135deg, rgba(136, 136, 136, 0.08), rgba(136, 136, 136, 0.04));
|
||||||
color: var(--settings-text);
|
border-color: rgba(136, 136, 136, 0.1);
|
||||||
}
|
box-shadow: none;
|
||||||
|
|
||||||
&.expanded {
|
.extension-icon-img {
|
||||||
color: var(--settings-accent);
|
opacity: 0.4;
|
||||||
background-color: var(--settings-hover);
|
filter: grayscale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-placeholder {
|
.extension-icon-img {
|
||||||
width: 24px;
|
width: 28px;
|
||||||
height: 24px;
|
height: 28px;
|
||||||
flex-shrink: 0;
|
object-fit: contain;
|
||||||
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-config {
|
.extension-info {
|
||||||
background-color: var(--settings-input-bg);
|
flex: 1;
|
||||||
border-left: 2px solid var(--settings-accent);
|
min-width: 0;
|
||||||
margin: 4px 0 12px 0;
|
}
|
||||||
padding: 8px 10px;
|
|
||||||
border-radius: 2px;
|
.extension-name {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--settings-text);
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.extension-description {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
color: var(--settings-text-secondary);
|
||||||
|
line-height: 1.5;
|
||||||
|
word-wrap: break-word;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.extension-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.extension-toggle-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background-color: var(--settings-input-bg);
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid var(--settings-input-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-label {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--settings-text);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.extension-config-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-header {
|
.config-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-title {
|
.config-title {
|
||||||
@@ -351,10 +425,10 @@ const handleConfigInput = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
.reset-button {
|
.reset-button {
|
||||||
padding: 3px 8px;
|
padding: 4px 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border: 1px solid var(--settings-input-border);
|
border: 1px solid var(--settings-input-border);
|
||||||
border-radius: 2px;
|
border-radius: 3px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: var(--settings-text-secondary);
|
color: var(--settings-text-secondary);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -370,7 +444,7 @@ const handleConfigInput = async (
|
|||||||
|
|
||||||
.config-table-wrapper {
|
.config-table-wrapper {
|
||||||
border: 1px solid var(--settings-input-border);
|
border: 1px solid var(--settings-input-border);
|
||||||
border-radius: 2px;
|
border-radius: 4px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: var(--settings-panel, var(--settings-input-bg));
|
background-color: var(--settings-panel, var(--settings-input-bg));
|
||||||
}
|
}
|
||||||
@@ -378,7 +452,7 @@ const handleConfigInput = async (
|
|||||||
.config-table {
|
.config-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-size: 11px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-table tr + tr {
|
.config-table tr + tr {
|
||||||
@@ -387,7 +461,7 @@ const handleConfigInput = async (
|
|||||||
|
|
||||||
.config-table th,
|
.config-table th,
|
||||||
.config-table td {
|
.config-table td {
|
||||||
padding: 5px 8px;
|
padding: 6px 10px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,36 +473,36 @@ const handleConfigInput = async (
|
|||||||
border-right: 1px solid var(--settings-input-border);
|
border-right: 1px solid var(--settings-input-border);
|
||||||
background-color: rgba(0, 0, 0, 0.05);
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
|
font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
|
||||||
font-size: 10px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-table-value {
|
.config-table-value {
|
||||||
padding: 3px 4px;
|
padding: 4px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-value-input {
|
.config-value-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 4px 6px;
|
padding: 5px 8px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: 2px;
|
border-radius: 3px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--settings-text);
|
color: var(--settings-text);
|
||||||
font-size: 11px;
|
font-size: 12px;
|
||||||
font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
|
font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
|
||||||
line-height: 1.3;
|
line-height: 1.4;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
transition: border-color 0.15s ease, background-color 0.15s ease;
|
transition: border-color 0.15s ease, background-color 0.15s ease;
|
||||||
}
|
|
||||||
|
|
||||||
.config-value-input:hover {
|
&:hover {
|
||||||
border-color: var(--settings-input-border);
|
border-color: var(--settings-input-border);
|
||||||
background-color: var(--settings-hover);
|
background-color: var(--settings-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-value-input:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: var(--settings-accent);
|
border-color: var(--settings-accent);
|
||||||
background-color: var(--settings-input-bg);
|
background-color: var(--settings-input-bg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const {
|
|||||||
setDataPath,
|
setDataPath,
|
||||||
setEnableGlobalHotkey,
|
setEnableGlobalHotkey,
|
||||||
setEnableLoadingAnimation,
|
setEnableLoadingAnimation,
|
||||||
|
setEnableMemoryMonitor,
|
||||||
setEnableSystemTray,
|
setEnableSystemTray,
|
||||||
setEnableTabs,
|
setEnableTabs,
|
||||||
setEnableWindowSnap,
|
setEnableWindowSnap,
|
||||||
@@ -137,6 +138,12 @@ const enableTabs = computed({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 计算属性 - 启用内存监视器
|
||||||
|
const enableMemoryMonitor = computed({
|
||||||
|
get: () => general.enableMemoryMonitor,
|
||||||
|
set: (value: boolean) => setEnableMemoryMonitor(value)
|
||||||
|
});
|
||||||
|
|
||||||
// 计算属性 - 开机启动
|
// 计算属性 - 开机启动
|
||||||
const startAtLogin = computed({
|
const startAtLogin = computed({
|
||||||
get: () => general.startAtLogin,
|
get: () => general.startAtLogin,
|
||||||
@@ -273,6 +280,9 @@ const selectDataDirectory = async () => {
|
|||||||
<SettingItem :title="t('settings.enableTabs')">
|
<SettingItem :title="t('settings.enableTabs')">
|
||||||
<ToggleSwitch v-model="enableTabs"/>
|
<ToggleSwitch v-model="enableTabs"/>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
<SettingItem :title="t('settings.enableMemoryMonitor')">
|
||||||
|
<ToggleSwitch v-model="enableMemoryMonitor"/>
|
||||||
|
</SettingItem>
|
||||||
</SettingSection>
|
</SettingSection>
|
||||||
|
|
||||||
<SettingSection :title="t('settings.startup')">
|
<SettingSection :title="t('settings.startup')">
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { onMounted, computed, ref, onUnmounted, watch } from 'vue';
|
import { onMounted, computed, ref, nextTick } from 'vue';
|
||||||
import SettingSection from '../components/SettingSection.vue';
|
import SettingSection from '../components/SettingSection.vue';
|
||||||
import SettingItem from '../components/SettingItem.vue';
|
import SettingItem from '../components/SettingItem.vue';
|
||||||
|
import { AccordionContainer, AccordionItem } from '@/components/accordion';
|
||||||
import { useKeybindingStore } from '@/stores/keybindingStore';
|
import { useKeybindingStore } from '@/stores/keybindingStore';
|
||||||
import { useSystemStore } from '@/stores/systemStore';
|
import { useSystemStore } from '@/stores/systemStore';
|
||||||
import { useConfigStore } from '@/stores/configStore';
|
import { useConfigStore } from '@/stores/configStore';
|
||||||
@@ -11,6 +12,7 @@ import { getCommandDescription } from '@/views/editor/keymap/commands';
|
|||||||
import { KeyBindingType } from '@/../bindings/voidraft/internal/models/models';
|
import { KeyBindingType } from '@/../bindings/voidraft/internal/models/models';
|
||||||
import { KeyBindingService } from '@/../bindings/voidraft/internal/services';
|
import { KeyBindingService } from '@/../bindings/voidraft/internal/services';
|
||||||
import { useConfirm } from '@/composables/useConfirm';
|
import { useConfirm } from '@/composables/useConfirm';
|
||||||
|
import toast from '@/components/toast';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const keybindingStore = useKeybindingStore();
|
const keybindingStore = useKeybindingStore();
|
||||||
@@ -20,16 +22,26 @@ const editorStore = useEditorStore();
|
|||||||
|
|
||||||
interface EditingState {
|
interface EditingState {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
|
||||||
originalKey: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const editingBinding = ref<EditingState | null>(null);
|
const editingBinding = ref<EditingState | null>(null);
|
||||||
const capturedKey = ref('');
|
const inputKey = ref('');
|
||||||
const capturedKeyDisplay = ref<string[]>([]);
|
|
||||||
const isConflict = ref(false);
|
|
||||||
|
|
||||||
const isEditing = computed(() => !!editingBinding.value);
|
// 将快捷键字符串拆分为独立的键
|
||||||
|
const splitKeys = (keyStr: string): string[] => {
|
||||||
|
if (!keyStr) return [];
|
||||||
|
return keyStr.split(/[-+]/).filter(Boolean);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 动态设置 ref 并自动聚焦
|
||||||
|
const setInputRef = (el: any) => {
|
||||||
|
if (el && el instanceof HTMLInputElement) {
|
||||||
|
// 使用 nextTick 确保 DOM 完全渲染后再聚焦
|
||||||
|
nextTick(() => {
|
||||||
|
el.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await keybindingStore.loadKeyBindings();
|
await keybindingStore.loadKeyBindings();
|
||||||
@@ -63,7 +75,10 @@ const keyBindings = computed(() =>
|
|||||||
command: getDisplayKeybinding(kb),
|
command: getDisplayKeybinding(kb),
|
||||||
rawKey: getRawKey(kb),
|
rawKey: getRawKey(kb),
|
||||||
extension: kb.extension || '',
|
extension: kb.extension || '',
|
||||||
description: getCommandDescription(kb.name) || kb.name || ''
|
description: getCommandDescription(kb.name) || kb.name || '',
|
||||||
|
enabled: kb.enabled,
|
||||||
|
preventDefault: kb.preventDefault,
|
||||||
|
originalData: kb
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -82,6 +97,8 @@ const getDisplayKeybinding = (kb: any): string[] => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const parseKeyString = (keyStr: string): string[] => {
|
const parseKeyString = (keyStr: string): string[] => {
|
||||||
|
if (!keyStr) return [];
|
||||||
|
|
||||||
const symbolMap: Record<string, string> = {
|
const symbolMap: Record<string, string> = {
|
||||||
'Mod': systemStore.isMacOS ? '⌘' : 'Ctrl',
|
'Mod': systemStore.isMacOS ? '⌘' : 'Ctrl',
|
||||||
'Cmd': '⌘',
|
'Cmd': '⌘',
|
||||||
@@ -102,128 +119,141 @@ const parseKeyString = (keyStr: string): string[] => {
|
|||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 切换启用状态
|
||||||
// 键盘事件捕获
|
const toggleEnabled = async (binding: any) => {
|
||||||
const SPECIAL_KEYS: Record<string, string> = {
|
try {
|
||||||
' ': 'Space',
|
await KeyBindingService.UpdateKeyBindingEnabled(binding.id, !binding.enabled);
|
||||||
'ArrowUp': 'ArrowUp',
|
await keybindingStore.loadKeyBindings();
|
||||||
'ArrowDown': 'ArrowDown',
|
await editorStore.applyKeymapSettings();
|
||||||
'ArrowLeft': 'ArrowLeft',
|
} catch (error) {
|
||||||
'ArrowRight': 'ArrowRight',
|
console.error('Failed to update enabled status:', error);
|
||||||
'Enter': 'Enter',
|
}
|
||||||
'Tab': 'Tab',
|
|
||||||
'Backspace': 'Backspace',
|
|
||||||
'Delete': 'Delete',
|
|
||||||
'Home': 'Home',
|
|
||||||
'End': 'End',
|
|
||||||
'PageUp': 'PageUp',
|
|
||||||
'PageDown': 'PageDown',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const MODIFIER_KEYS = ['Control', 'Alt', 'Shift', 'Meta'];
|
// 切换 PreventDefault
|
||||||
const MAX_KEY_PARTS = 3; // 最多3个键
|
const togglePreventDefault = async (binding: any) => {
|
||||||
|
try {
|
||||||
const captureKeyBinding = (event: KeyboardEvent): string | null => {
|
await KeyBindingService.UpdateKeyBindingPreventDefault(binding.id, !binding.preventDefault);
|
||||||
// 忽略单独的修饰键
|
await keybindingStore.loadKeyBindings();
|
||||||
if (MODIFIER_KEYS.includes(event.key)) return null;
|
await editorStore.applyKeymapSettings();
|
||||||
|
} catch (error) {
|
||||||
const parts: string[] = [];
|
console.error('Failed to update preventDefault:', error);
|
||||||
|
}
|
||||||
// 添加修饰键
|
|
||||||
if (event.ctrlKey || event.metaKey) parts.push('Mod');
|
|
||||||
if (event.altKey) parts.push('Alt');
|
|
||||||
if (event.shiftKey) parts.push('Shift');
|
|
||||||
|
|
||||||
// 获取主键
|
|
||||||
const mainKey = SPECIAL_KEYS[event.key] ??
|
|
||||||
(event.key.length === 1 ? event.key.toLowerCase() : event.key);
|
|
||||||
|
|
||||||
if (mainKey) parts.push(mainKey);
|
|
||||||
|
|
||||||
// 限制最多3个键
|
|
||||||
if (parts.length > MAX_KEY_PARTS) return null;
|
|
||||||
|
|
||||||
return parts.join('-');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 开始添加快捷键
|
||||||
|
const startAddKey = (bindingId: number) => {
|
||||||
|
editingBinding.value = {
|
||||||
|
id: bindingId
|
||||||
|
};
|
||||||
|
inputKey.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消编辑
|
||||||
const cancelEdit = () => {
|
const cancelEdit = () => {
|
||||||
window.removeEventListener('keydown', handleKeyCapture, true);
|
|
||||||
editingBinding.value = null;
|
editingBinding.value = null;
|
||||||
capturedKey.value = '';
|
inputKey.value = '';
|
||||||
capturedKeyDisplay.value = [];
|
|
||||||
isConflict.value = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleKeyCapture = (event: KeyboardEvent) => {
|
// 验证快捷键格式
|
||||||
if (!isEditing.value) return;
|
const validateKeyFormat = (key: string): boolean => {
|
||||||
|
if (!key || key.trim() === '') return false;
|
||||||
|
|
||||||
event.preventDefault();
|
// 基本格式验证:允许 Mod/Ctrl/Alt/Shift + 其他键
|
||||||
event.stopPropagation();
|
const validPattern = /^(Mod|Ctrl|Alt|Shift|Cmd)(-[A-Za-z0-9\[\]\\/;',.\-=`]|-(ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Enter|Tab|Backspace|Delete|Home|End|PageUp|PageDown|Space|Escape))+$/;
|
||||||
|
const simpleKeyPattern = /^[A-Za-z0-9]$/;
|
||||||
|
const specialKeyPattern = /^(ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Enter|Tab|Backspace|Delete|Home|End|PageUp|PageDown|Space|Escape)$/;
|
||||||
|
|
||||||
// ESC 取消编辑
|
return validPattern.test(key) || simpleKeyPattern.test(key) || specialKeyPattern.test(key);
|
||||||
if (event.key === 'Escape') {
|
};
|
||||||
cancelEdit();
|
|
||||||
|
// 检查快捷键冲突
|
||||||
|
const checkConflict = (newKey: string, currentBindingId: number): { conflict: boolean; conflictWith?: string } => {
|
||||||
|
const conflictBinding = keyBindings.value.find(kb =>
|
||||||
|
kb.rawKey === newKey && kb.id !== currentBindingId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (conflictBinding) {
|
||||||
|
return {
|
||||||
|
conflict: true,
|
||||||
|
conflictWith: conflictBinding.description
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { conflict: false };
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加新键到快捷键
|
||||||
|
const addKeyPart = async () => {
|
||||||
|
if (!editingBinding.value || !inputKey.value.trim()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = captureKeyBinding(event);
|
const newPart = inputKey.value.trim();
|
||||||
if (key) {
|
const binding = keyBindings.value.find(kb => kb.id === editingBinding.value!.id);
|
||||||
capturedKey.value = key;
|
if (!binding) return;
|
||||||
capturedKeyDisplay.value = parseKeyString(key);
|
|
||||||
isConflict.value = false;
|
// 检查键数量限制(最多4个)
|
||||||
|
const currentParts = splitKeys(binding.rawKey);
|
||||||
|
if (currentParts.length >= 4) {
|
||||||
|
toast.error(t('keybindings.maxKeysReached'));
|
||||||
|
inputKey.value = '';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
// 获取现有的键
|
||||||
|
const currentKey = binding.rawKey;
|
||||||
|
const newKey = currentKey ? `${currentKey}-${newPart}` : newPart;
|
||||||
|
|
||||||
const startEditBinding = (binding: any) => {
|
// 验证格式
|
||||||
editingBinding.value = {
|
if (!validateKeyFormat(newKey)) {
|
||||||
id: binding.id,
|
toast.error(t('keybindings.invalidFormat'));
|
||||||
name: binding.name,
|
inputKey.value = '';
|
||||||
originalKey: binding.rawKey
|
return;
|
||||||
};
|
}
|
||||||
capturedKey.value = '';
|
|
||||||
capturedKeyDisplay.value = [];
|
|
||||||
isConflict.value = false;
|
|
||||||
|
|
||||||
// 手动添加键盘监听
|
|
||||||
window.addEventListener('keydown', handleKeyCapture, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkConflict = (newKey: string): boolean =>
|
|
||||||
keyBindings.value.some(kb =>
|
|
||||||
kb.rawKey === newKey && kb.name !== editingBinding.value?.name
|
|
||||||
);
|
|
||||||
|
|
||||||
const confirmKeybinding = async () => {
|
|
||||||
if (!editingBinding.value || !capturedKey.value) return;
|
|
||||||
|
|
||||||
// 检查冲突
|
// 检查冲突
|
||||||
if (checkConflict(capturedKey.value)) {
|
const conflictCheck = checkConflict(newKey, editingBinding.value.id);
|
||||||
isConflict.value = true;
|
if (conflictCheck.conflict) {
|
||||||
setTimeout(cancelEdit, 600);
|
toast.error(t('keybindings.conflict', { command: conflictCheck.conflictWith }));
|
||||||
|
inputKey.value = '';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await keybindingStore.updateKeyBinding(
|
await keybindingStore.updateKeyBinding(editingBinding.value.id, newKey);
|
||||||
editingBinding.value.id,
|
|
||||||
capturedKey.value
|
|
||||||
);
|
|
||||||
await editorStore.applyKeymapSettings();
|
await editorStore.applyKeymapSettings();
|
||||||
|
inputKey.value = '';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error('Failed to add key part:', error);
|
||||||
} finally {
|
|
||||||
cancelEdit();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 删除快捷键的某个部分
|
||||||
|
const removeKeyPart = async (bindingId: number, index: number) => {
|
||||||
|
const binding = keyBindings.value.find(kb => kb.id === bindingId);
|
||||||
|
if (!binding) return;
|
||||||
|
|
||||||
|
const parts = splitKeys(binding.rawKey);
|
||||||
|
parts.splice(index, 1);
|
||||||
|
|
||||||
|
const newKey = parts.join('-');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await keybindingStore.updateKeyBinding(bindingId, newKey);
|
||||||
|
await editorStore.applyKeymapSettings();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to remove key part:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="settings-page">
|
<div class="settings-page">
|
||||||
<!-- 快捷键模式设置 -->
|
<!-- 快捷键模式设置 -->
|
||||||
<SettingSection :title="t('keybindings.keymapMode')">
|
<SettingSection :title="t('keybindings.keymapMode')">
|
||||||
<SettingItem
|
<SettingItem :title="t('keybindings.keymapMode')">
|
||||||
:title="t('keybindings.keymapMode')">
|
|
||||||
<select
|
<select
|
||||||
:value="configStore.config.editing.keymapMode"
|
:value="configStore.config.editing.keymapMode"
|
||||||
@change="updateKeymapMode(($event.target as HTMLSelectElement).value as KeyBindingType)"
|
@change="updateKeymapMode(($event.target as HTMLSelectElement).value as KeyBindingType)"
|
||||||
@@ -251,68 +281,111 @@ const confirmKeybinding = async () => {
|
|||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="key-bindings-container">
|
<AccordionContainer :multiple="false">
|
||||||
<div class="key-bindings-header">
|
<AccordionItem
|
||||||
<div class="keybinding-col">{{ t('keybindings.headers.shortcut') }}</div>
|
|
||||||
<div class="extension-col">{{ t('keybindings.headers.extension') }}</div>
|
|
||||||
<div class="description-col">{{ t('keybindings.headers.description') }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-for="binding in keyBindings"
|
v-for="binding in keyBindings"
|
||||||
:key="binding.name"
|
:key="binding.id"
|
||||||
class="key-binding-row"
|
:id="binding.id!"
|
||||||
>
|
>
|
||||||
<!-- 快捷键列 -->
|
<!-- 标题插槽 -->
|
||||||
<div
|
<template #title>
|
||||||
class="keybinding-col"
|
<div class="binding-title" :class="{ 'disabled': !binding.enabled }">
|
||||||
:class="{ 'editing': editingBinding?.name === binding.name }"
|
<div class="binding-name">
|
||||||
@click.stop="editingBinding?.name !== binding.name && startEditBinding(binding)"
|
<span class="binding-description">{{ binding.description }}</span>
|
||||||
>
|
<span class="binding-extension">{{ binding.extension }}</span>
|
||||||
<!-- 编辑模式 -->
|
</div>
|
||||||
<template v-if="editingBinding?.name === binding.name">
|
<div class="binding-keys">
|
||||||
<template v-if="!capturedKey">
|
|
||||||
<span class="key-badge waiting">waiting...</span>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<span
|
<span
|
||||||
v-for="(key, index) in capturedKeyDisplay"
|
v-for="(key, index) in binding.command"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="key-badge captured"
|
class="key-badge"
|
||||||
:class="{ 'conflict': isConflict }"
|
|
||||||
>
|
>
|
||||||
{{ key }}
|
{{ key }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
<span v-if="!binding.command.length" class="key-badge-empty">-</span>
|
||||||
<button
|
</div>
|
||||||
@click.stop="confirmKeybinding"
|
</div>
|
||||||
class="btn-mini btn-confirm"
|
</template>
|
||||||
:disabled="!capturedKey"
|
|
||||||
title="Ok"
|
|
||||||
>✓</button>
|
|
||||||
<button
|
|
||||||
@click.stop="cancelEdit"
|
|
||||||
class="btn-mini btn-cancel"
|
|
||||||
title="Cancel"
|
|
||||||
>✕</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 显示模式 -->
|
<!-- 展开内容 -->
|
||||||
<template v-else>
|
<div class="binding-config">
|
||||||
<span
|
<!-- Enabled 配置 -->
|
||||||
v-for="(key, index) in binding.command"
|
<div class="config-row">
|
||||||
:key="index"
|
<span class="config-label">{{ t('keybindings.config.enabled') }}</span>
|
||||||
class="key-badge"
|
<label class="switch">
|
||||||
>
|
<input
|
||||||
{{ key }}
|
type="checkbox"
|
||||||
</span>
|
:checked="binding.enabled"
|
||||||
</template>
|
@change="toggleEnabled(binding)"
|
||||||
|
>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- PreventDefault 配置 -->
|
||||||
|
<div class="config-row">
|
||||||
|
<span class="config-label">{{ t('keybindings.config.preventDefault') }}</span>
|
||||||
|
<label class="switch">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
:checked="binding.preventDefault"
|
||||||
|
@change="togglePreventDefault(binding)"
|
||||||
|
>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Key 配置 -->
|
||||||
|
<div class="config-row">
|
||||||
|
<span class="config-label">{{ t('keybindings.config.keybinding') }}</span>
|
||||||
|
<div class="key-input-wrapper">
|
||||||
|
<div class="key-tags">
|
||||||
|
<!-- 显示现有快捷键的每个部分 -->
|
||||||
|
<template v-if="binding.rawKey">
|
||||||
|
<span
|
||||||
|
v-for="(keyPart, index) in splitKeys(binding.rawKey)"
|
||||||
|
:key="index"
|
||||||
|
class="key-tag"
|
||||||
|
>
|
||||||
|
<span class="key-tag-text">{{ keyPart }}</span>
|
||||||
|
<button
|
||||||
|
class="key-tag-remove"
|
||||||
|
@click="removeKeyPart(binding.id!, index)"
|
||||||
|
>×</button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 添加输入框 -->
|
||||||
|
<template v-if="editingBinding?.id === binding.id">
|
||||||
|
<input
|
||||||
|
:ref="setInputRef"
|
||||||
|
v-model="inputKey"
|
||||||
|
type="text"
|
||||||
|
class="key-input"
|
||||||
|
:placeholder="t('keybindings.keyPlaceholder')"
|
||||||
|
@keydown.enter="addKeyPart"
|
||||||
|
@keydown.escape="cancelEdit"
|
||||||
|
@blur="cancelEdit"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 添加按钮 -->
|
||||||
|
<template v-else>
|
||||||
|
<button
|
||||||
|
class="key-tag-add"
|
||||||
|
@click="startAddKey(binding.id!)"
|
||||||
|
>
|
||||||
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M6 1V11M1 6H11" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</AccordionItem>
|
||||||
<div class="extension-col">{{ binding.extension }}</div>
|
</AccordionContainer>
|
||||||
<div class="description-col">{{ binding.description }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SettingSection>
|
</SettingSection>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -375,167 +448,275 @@ const confirmKeybinding = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.key-bindings-container {
|
.binding-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
.key-bindings-header {
|
&.disabled {
|
||||||
display: flex;
|
opacity: 0.5;
|
||||||
padding: 0 0 8px 0;
|
|
||||||
border-bottom: 1px solid var(--settings-border);
|
|
||||||
color: var(--text-muted);
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-binding-row {
|
|
||||||
display: flex;
|
|
||||||
padding: 10px 0;
|
|
||||||
border-bottom: 1px solid var(--settings-border);
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--settings-hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.keybinding-col {
|
|
||||||
width: 150px;
|
|
||||||
display: flex;
|
|
||||||
gap: 4px;
|
|
||||||
padding: 0 10px 0 0;
|
|
||||||
color: var(--settings-text);
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
|
|
||||||
&:hover:not(.editing) .key-badge {
|
|
||||||
border-color: #4a9eff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.editing {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-badge {
|
|
||||||
background-color: var(--settings-input-bg);
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: 11px;
|
|
||||||
border: 1px solid var(--settings-input-border);
|
|
||||||
color: var(--settings-text);
|
|
||||||
transition: border-color 0.2s ease;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
&.waiting {
|
|
||||||
border: none;
|
|
||||||
background-color: transparent;
|
|
||||||
padding: 0;
|
|
||||||
color: #4a9eff;
|
|
||||||
font-style: italic;
|
|
||||||
animation: colorPulse 1.5s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.captured {
|
|
||||||
background-color: #4a9eff;
|
|
||||||
color: white;
|
|
||||||
border-color: #4a9eff;
|
|
||||||
|
|
||||||
&.conflict {
|
|
||||||
background-color: #dc3545;
|
|
||||||
border-color: #dc3545;
|
|
||||||
animation: shake 0.6s ease-in-out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-mini {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
min-width: 16px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 2px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 10px;
|
|
||||||
transition: opacity 0.2s ease;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0;
|
|
||||||
line-height: 1;
|
|
||||||
margin-left: auto;
|
|
||||||
|
|
||||||
&.btn-confirm {
|
|
||||||
background-color: #28a745;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
background-color: var(--settings-input-border);
|
|
||||||
cursor: not-allowed;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.btn-cancel {
|
|
||||||
background-color: #dc3545;
|
|
||||||
color: white;
|
|
||||||
margin-left: 2px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.extension-col {
|
|
||||||
width: 80px;
|
|
||||||
padding: 0 10px 0 0;
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--settings-text);
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description-col {
|
|
||||||
flex: 1;
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--settings-text);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes colorPulse {
|
.binding-name {
|
||||||
0%, 100% {
|
flex: 1;
|
||||||
color: #4a9eff;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.binding-description {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--settings-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.binding-extension {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.binding-keys {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-badge {
|
||||||
|
background-color: var(--settings-input-bg);
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 11px;
|
||||||
|
border: 1px solid var(--settings-input-border);
|
||||||
|
color: var(--settings-text);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-badge-empty {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.binding-config {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--settings-text);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch 开关样式
|
||||||
|
.switch {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 36px;
|
||||||
|
height: 20px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
input {
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
|
||||||
|
&:checked + .slider {
|
||||||
|
background-color: #4a9eff;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
transform: translateX(16px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus + .slider {
|
||||||
|
box-shadow: 0 0 1px #4a9eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: var(--settings-input-border);
|
||||||
|
transition: 0.3s;
|
||||||
|
border-radius: 20px;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
height: 14px;
|
||||||
|
width: 14px;
|
||||||
|
left: 3px;
|
||||||
|
bottom: 3px;
|
||||||
|
background-color: white;
|
||||||
|
transition: 0.3s;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-input-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-tags {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
height: 28px;
|
||||||
|
background-color: var(--settings-input-bg);
|
||||||
|
border: 1px solid var(--settings-input-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--settings-text);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #4a9eff;
|
||||||
|
|
||||||
|
.key-tag-remove {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-tag-text {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-tag-remove {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
color: var(--text-muted);
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0.6;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #e74c3c;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
50% {
|
|
||||||
color: #2080ff;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes shake {
|
.key-tag-add {
|
||||||
0%, 100% {
|
display: flex;
|
||||||
transform: translateX(0);
|
align-items: center;
|
||||||
}
|
justify-content: center;
|
||||||
10%, 30%, 50%, 70%, 90% {
|
width: 28px;
|
||||||
transform: translateX(-4px);
|
height: 28px;
|
||||||
}
|
flex-shrink: 0;
|
||||||
20%, 40%, 60%, 80% {
|
border: 1px dashed var(--settings-input-border);
|
||||||
transform: translateX(4px);
|
border-radius: 4px;
|
||||||
}
|
background-color: transparent;
|
||||||
}
|
|
||||||
|
|
||||||
.coming-soon-placeholder {
|
|
||||||
padding: 20px;
|
|
||||||
background-color: var(--settings-card-bg);
|
|
||||||
border-radius: 6px;
|
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
text-align: center;
|
cursor: pointer;
|
||||||
font-style: italic;
|
transition: all 0.2s ease;
|
||||||
font-size: 13px;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #4a9eff;
|
||||||
|
background-color: var(--settings-input-bg);
|
||||||
|
color: #4a9eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-input {
|
||||||
|
padding: 4px 8px;
|
||||||
|
height: 28px;
|
||||||
|
border: 1px solid #4a9eff;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: var(--settings-input-bg);
|
||||||
|
color: var(--settings-text);
|
||||||
|
font-size: 12px;
|
||||||
|
width: 60px;
|
||||||
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-mini {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
min-width: 24px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&.btn-confirm {
|
||||||
|
background-color: #28a745;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background-color: var(--settings-input-border);
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-cancel {
|
||||||
|
background-color: #dc3545;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -79,6 +79,7 @@ type GeneralConfig struct {
|
|||||||
// 界面设置
|
// 界面设置
|
||||||
EnableLoadingAnimation bool `json:"enableLoadingAnimation"` // 是否启用加载动画
|
EnableLoadingAnimation bool `json:"enableLoadingAnimation"` // 是否启用加载动画
|
||||||
EnableTabs bool `json:"enableTabs"` // 是否启用标签页模式
|
EnableTabs bool `json:"enableTabs"` // 是否启用标签页模式
|
||||||
|
EnableMemoryMonitor bool `json:"enableMemoryMonitor"` // 是否启用内存监视器
|
||||||
}
|
}
|
||||||
|
|
||||||
// HotkeyCombo 热键组合定义
|
// HotkeyCombo 热键组合定义
|
||||||
@@ -188,6 +189,7 @@ func NewDefaultAppConfig() *AppConfig {
|
|||||||
EnableGlobalHotkey: false,
|
EnableGlobalHotkey: false,
|
||||||
EnableLoadingAnimation: true, // 默认启用加载动画
|
EnableLoadingAnimation: true, // 默认启用加载动画
|
||||||
EnableTabs: false, // 默认不启用标签页模式
|
EnableTabs: false, // 默认不启用标签页模式
|
||||||
|
EnableMemoryMonitor: true, // 默认启用内存监视器
|
||||||
GlobalHotkey: HotkeyCombo{
|
GlobalHotkey: HotkeyCombo{
|
||||||
Ctrl: false,
|
Ctrl: false,
|
||||||
Shift: false,
|
Shift: false,
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ const (
|
|||||||
CopyBlockImage KeyBindingName = "copyBlockImage" // 复制块为图片
|
CopyBlockImage KeyBindingName = "copyBlockImage" // 复制块为图片
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultExtension = "editor"
|
const DefaultExtension = "editor"
|
||||||
|
|
||||||
// NewDefaultKeyBindings 创建默认快捷键配置
|
// NewDefaultKeyBindings 创建默认快捷键配置
|
||||||
func NewDefaultKeyBindings() []KeyBinding {
|
func NewDefaultKeyBindings() []KeyBinding {
|
||||||
@@ -135,7 +135,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockSelectAll,
|
Name: BlockSelectAll,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-a",
|
Key: "Mod-a",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -143,7 +143,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockAddAfterCurrent,
|
Name: BlockAddAfterCurrent,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Enter",
|
Key: "Mod-Enter",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -151,7 +151,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockAddAfterLast,
|
Name: BlockAddAfterLast,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-Enter",
|
Key: "Mod-Shift-Enter",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -159,7 +159,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockAddBeforeCurrent,
|
Name: BlockAddBeforeCurrent,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Alt-Enter",
|
Key: "Alt-Enter",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -167,7 +167,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockGotoPrevious,
|
Name: BlockGotoPrevious,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-ArrowUp",
|
Key: "Mod-ArrowUp",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -175,7 +175,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockGotoNext,
|
Name: BlockGotoNext,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-ArrowDown",
|
Key: "Mod-ArrowDown",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -183,7 +183,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockSelectPrevious,
|
Name: BlockSelectPrevious,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-ArrowUp",
|
Key: "Mod-Shift-ArrowUp",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -191,7 +191,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockSelectNext,
|
Name: BlockSelectNext,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-ArrowDown",
|
Key: "Mod-Shift-ArrowDown",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -199,7 +199,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockDelete,
|
Name: BlockDelete,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-d",
|
Key: "Mod-Shift-d",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -207,7 +207,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockMoveUp,
|
Name: BlockMoveUp,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-Mod-ArrowUp",
|
Key: "Shift-Mod-ArrowUp",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -215,7 +215,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockMoveDown,
|
Name: BlockMoveDown,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-Mod-ArrowDown",
|
Key: "Shift-Mod-ArrowDown",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -223,7 +223,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockDeleteLine,
|
Name: BlockDeleteLine,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-k",
|
Key: "Mod-Shift-k",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -231,7 +231,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockMoveLineUp,
|
Name: BlockMoveLineUp,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Alt-ArrowUp",
|
Key: "Alt-ArrowUp",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -239,7 +239,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockMoveLineDown,
|
Name: BlockMoveLineDown,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Alt-ArrowDown",
|
Key: "Alt-ArrowDown",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -247,7 +247,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockTransposeChars,
|
Name: BlockTransposeChars,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-t",
|
Key: "Mod-t",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -255,7 +255,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockFormat,
|
Name: BlockFormat,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-f",
|
Key: "Mod-Shift-f",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -263,7 +263,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockCopy,
|
Name: BlockCopy,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-c",
|
Key: "Mod-c",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -271,7 +271,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockCut,
|
Name: BlockCut,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-x",
|
Key: "Mod-x",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -279,7 +279,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockPaste,
|
Name: BlockPaste,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-v",
|
Key: "Mod-v",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -335,7 +335,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: HistoryUndo,
|
Name: HistoryUndo,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-z",
|
Key: "Mod-z",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -344,7 +344,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-z",
|
Key: "Mod-Shift-z",
|
||||||
Windows: "Ctrl-y",
|
Windows: "Ctrl-y",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -352,7 +352,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: HistoryUndoSelection,
|
Name: HistoryUndoSelection,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-u",
|
Key: "Mod-u",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -361,7 +361,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-u",
|
Key: "Mod-Shift-u",
|
||||||
Windows: "Alt-u",
|
Windows: "Alt-u",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -373,7 +373,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Macos: "Ctrl-ArrowLeft",
|
Macos: "Ctrl-ArrowLeft",
|
||||||
Windows: "Alt-ArrowLeft",
|
Windows: "Alt-ArrowLeft",
|
||||||
Linux: "Alt-ArrowLeft",
|
Linux: "Alt-ArrowLeft",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -383,7 +383,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Macos: "Ctrl-ArrowRight",
|
Macos: "Ctrl-ArrowRight",
|
||||||
Windows: "Alt-ArrowRight",
|
Windows: "Alt-ArrowRight",
|
||||||
Linux: "Alt-ArrowRight",
|
Linux: "Alt-ArrowRight",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -391,7 +391,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectSyntaxLeft,
|
Name: SelectSyntaxLeft,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-Alt-ArrowLeft",
|
Key: "Shift-Alt-ArrowLeft",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -399,7 +399,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectSyntaxRight,
|
Name: SelectSyntaxRight,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-Alt-ArrowRight",
|
Key: "Shift-Alt-ArrowRight",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -407,7 +407,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CopyLineUp,
|
Name: CopyLineUp,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-Alt-ArrowUp",
|
Key: "Shift-Alt-ArrowUp",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -415,7 +415,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CopyLineDown,
|
Name: CopyLineDown,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-Alt-ArrowDown",
|
Key: "Shift-Alt-ArrowDown",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -423,9 +423,9 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: InsertBlankLine,
|
Name: InsertBlankLine,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Enter",
|
Key: "Mod-Enter",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: false,
|
||||||
PreventDefault: true,
|
PreventDefault: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: SelectLine,
|
Name: SelectLine,
|
||||||
@@ -433,7 +433,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Macos: "Ctrl-l",
|
Macos: "Ctrl-l",
|
||||||
Windows: "Alt-l",
|
Windows: "Alt-l",
|
||||||
Linux: "Alt-l",
|
Linux: "Alt-l",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -441,7 +441,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectParentSyntax,
|
Name: SelectParentSyntax,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-i",
|
Key: "Mod-i",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -449,7 +449,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SimplifySelection,
|
Name: SimplifySelection,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Escape",
|
Key: "Escape",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: false,
|
PreventDefault: false,
|
||||||
},
|
},
|
||||||
@@ -459,7 +459,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Macos: "Cmd-Alt-ArrowUp",
|
Macos: "Cmd-Alt-ArrowUp",
|
||||||
Windows: "Ctrl-Alt-ArrowUp",
|
Windows: "Ctrl-Alt-ArrowUp",
|
||||||
Linux: "Ctrl-Alt-ArrowUp",
|
Linux: "Ctrl-Alt-ArrowUp",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -469,7 +469,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Macos: "Cmd-Alt-ArrowDown",
|
Macos: "Cmd-Alt-ArrowDown",
|
||||||
Windows: "Ctrl-Alt-ArrowDown",
|
Windows: "Ctrl-Alt-ArrowDown",
|
||||||
Linux: "Ctrl-Alt-ArrowDown",
|
Linux: "Ctrl-Alt-ArrowDown",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -479,7 +479,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Windows: "Ctrl-ArrowLeft",
|
Windows: "Ctrl-ArrowLeft",
|
||||||
Linux: "Ctrl-ArrowLeft",
|
Linux: "Ctrl-ArrowLeft",
|
||||||
Macos: "Alt-ArrowLeft",
|
Macos: "Alt-ArrowLeft",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -489,7 +489,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Windows: "Ctrl-ArrowRight",
|
Windows: "Ctrl-ArrowRight",
|
||||||
Linux: "Ctrl-ArrowRight",
|
Linux: "Ctrl-ArrowRight",
|
||||||
Macos: "Alt-ArrowRight",
|
Macos: "Alt-ArrowRight",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -499,7 +499,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Windows: "Ctrl-Shift-ArrowLeft",
|
Windows: "Ctrl-Shift-ArrowLeft",
|
||||||
Linux: "Ctrl-Shift-ArrowLeft",
|
Linux: "Ctrl-Shift-ArrowLeft",
|
||||||
Macos: "Alt-Shift-ArrowLeft",
|
Macos: "Alt-Shift-ArrowLeft",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -509,7 +509,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Windows: "Ctrl-Shift-ArrowRight",
|
Windows: "Ctrl-Shift-ArrowRight",
|
||||||
Linux: "Ctrl-Shift-ArrowRight",
|
Linux: "Ctrl-Shift-ArrowRight",
|
||||||
Macos: "Alt-Shift-ArrowRight",
|
Macos: "Alt-Shift-ArrowRight",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -519,7 +519,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Macos: "Ctrl-k",
|
Macos: "Ctrl-k",
|
||||||
Windows: "Ctrl-k",
|
Windows: "Ctrl-k",
|
||||||
Linux: "Ctrl-k",
|
Linux: "Ctrl-k",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -527,7 +527,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: DeleteToLineStart,
|
Name: DeleteToLineStart,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-Backspace",
|
Key: "Mod-Shift-Backspace",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -535,7 +535,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorLineStart,
|
Name: CursorLineStart,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Home",
|
Key: "Home",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: false,
|
PreventDefault: false,
|
||||||
},
|
},
|
||||||
@@ -543,7 +543,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorLineEnd,
|
Name: CursorLineEnd,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "End",
|
Key: "End",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: false,
|
PreventDefault: false,
|
||||||
},
|
},
|
||||||
@@ -551,7 +551,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectLineStart,
|
Name: SelectLineStart,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-Home",
|
Key: "Shift-Home",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: false,
|
PreventDefault: false,
|
||||||
},
|
},
|
||||||
@@ -559,7 +559,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectLineEnd,
|
Name: SelectLineEnd,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-End",
|
Key: "Shift-End",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: false,
|
PreventDefault: false,
|
||||||
},
|
},
|
||||||
@@ -567,7 +567,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorDocStart,
|
Name: CursorDocStart,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Home",
|
Key: "Mod-Home",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -575,7 +575,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorDocEnd,
|
Name: CursorDocEnd,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-End",
|
Key: "Mod-End",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -583,7 +583,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectDocStart,
|
Name: SelectDocStart,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-Home",
|
Key: "Mod-Shift-Home",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -591,7 +591,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectDocEnd,
|
Name: SelectDocEnd,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-End",
|
Key: "Mod-Shift-End",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -599,7 +599,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectMatchingBracket,
|
Name: SelectMatchingBracket,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Shift-p",
|
Key: "Mod-Shift-p",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -609,7 +609,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Macos: "Ctrl-o",
|
Macos: "Ctrl-o",
|
||||||
Windows: "Ctrl-o",
|
Windows: "Ctrl-o",
|
||||||
Linux: "Ctrl-o",
|
Linux: "Ctrl-o",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -618,7 +618,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: IndentLess,
|
Name: IndentLess,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-[",
|
Key: "Mod-[",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -626,7 +626,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: IndentMore,
|
Name: IndentMore,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-]",
|
Key: "Mod-]",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -634,7 +634,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: IndentSelection,
|
Name: IndentSelection,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Alt-\\",
|
Key: "Mod-Alt-\\",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -642,7 +642,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorMatchingBracket,
|
Name: CursorMatchingBracket,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-Mod-\\",
|
Key: "Shift-Mod-\\",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -650,7 +650,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: ToggleComment,
|
Name: ToggleComment,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-/",
|
Key: "Mod-/",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -658,7 +658,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: ToggleBlockComment,
|
Name: ToggleBlockComment,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Shift-Alt-a",
|
Key: "Shift-Alt-a",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -667,7 +667,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: InsertNewlineAndIndent,
|
Name: InsertNewlineAndIndent,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Enter",
|
Key: "Enter",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: false,
|
PreventDefault: false,
|
||||||
},
|
},
|
||||||
@@ -675,7 +675,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: DeleteCharBackward,
|
Name: DeleteCharBackward,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Backspace",
|
Key: "Backspace",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: false,
|
PreventDefault: false,
|
||||||
},
|
},
|
||||||
@@ -683,7 +683,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: DeleteCharForward,
|
Name: DeleteCharForward,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Delete",
|
Key: "Delete",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: false,
|
PreventDefault: false,
|
||||||
},
|
},
|
||||||
@@ -691,7 +691,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: DeleteGroupBackward,
|
Name: DeleteGroupBackward,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Backspace",
|
Key: "Mod-Backspace",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -699,7 +699,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: DeleteGroupForward,
|
Name: DeleteGroupForward,
|
||||||
Type: Standard,
|
Type: Standard,
|
||||||
Key: "Mod-Delete",
|
Key: "Mod-Delete",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -712,7 +712,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorCharLeft,
|
Name: CursorCharLeft,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-b",
|
Key: "Ctrl-b",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -720,7 +720,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectCharLeft,
|
Name: SelectCharLeft,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Shift-Ctrl-b",
|
Key: "Shift-Ctrl-b",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -728,7 +728,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorCharRight,
|
Name: CursorCharRight,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-f",
|
Key: "Ctrl-f",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -736,7 +736,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectCharRight,
|
Name: SelectCharRight,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Shift-Ctrl-f",
|
Key: "Shift-Ctrl-f",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -746,7 +746,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorLineUp,
|
Name: CursorLineUp,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-p",
|
Key: "Ctrl-p",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -754,7 +754,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectLineUp,
|
Name: SelectLineUp,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Shift-Ctrl-p",
|
Key: "Shift-Ctrl-p",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -762,7 +762,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorLineDown,
|
Name: CursorLineDown,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-n",
|
Key: "Ctrl-n",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -770,7 +770,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectLineDown,
|
Name: SelectLineDown,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Shift-Ctrl-n",
|
Key: "Shift-Ctrl-n",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -780,7 +780,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorLineStart,
|
Name: CursorLineStart,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-a",
|
Key: "Ctrl-a",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -788,7 +788,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectLineStart,
|
Name: SelectLineStart,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Shift-Ctrl-a",
|
Key: "Shift-Ctrl-a",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -796,7 +796,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorLineEnd,
|
Name: CursorLineEnd,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-e",
|
Key: "Ctrl-e",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -804,7 +804,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SelectLineEnd,
|
Name: SelectLineEnd,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Shift-Ctrl-e",
|
Key: "Shift-Ctrl-e",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -814,7 +814,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorPageDown,
|
Name: CursorPageDown,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-v",
|
Key: "Ctrl-v",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -822,7 +822,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: CursorPageUp,
|
Name: CursorPageUp,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Alt-v",
|
Key: "Alt-v",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -832,7 +832,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: DeleteCharForward,
|
Name: DeleteCharForward,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-d",
|
Key: "Ctrl-d",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -840,7 +840,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: DeleteCharBackward,
|
Name: DeleteCharBackward,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-h",
|
Key: "Ctrl-h",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -848,7 +848,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: DeleteToLineEnd,
|
Name: DeleteToLineEnd,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-k",
|
Key: "Ctrl-k",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -856,7 +856,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: DeleteGroupBackward,
|
Name: DeleteGroupBackward,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-Alt-h",
|
Key: "Ctrl-Alt-h",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -864,7 +864,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: SplitLine,
|
Name: SplitLine,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-o",
|
Key: "Ctrl-o",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -872,7 +872,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockTransposeChars,
|
Name: BlockTransposeChars,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Ctrl-t",
|
Key: "Ctrl-t",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -882,7 +882,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockSelectAll,
|
Name: BlockSelectAll,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Mod-Shift-a",
|
Key: "Mod-Shift-a",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
@@ -890,7 +890,7 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
Name: BlockPaste,
|
Name: BlockPaste,
|
||||||
Type: Emacs,
|
Type: Emacs,
|
||||||
Key: "Mod-Shift-v",
|
Key: "Mod-Shift-v",
|
||||||
Extension: defaultExtension,
|
Extension: DefaultExtension,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PreventDefault: true,
|
PreventDefault: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"voidraft/internal/models"
|
"voidraft/internal/models"
|
||||||
|
|
||||||
"voidraft/internal/models/ent"
|
"voidraft/internal/models/ent"
|
||||||
|
"voidraft/internal/models/ent/extension"
|
||||||
"voidraft/internal/models/ent/keybinding"
|
"voidraft/internal/models/ent/keybinding"
|
||||||
"voidraft/internal/models/schema/mixin"
|
"voidraft/internal/models/schema/mixin"
|
||||||
|
|
||||||
@@ -112,45 +113,74 @@ func (s *KeyBindingService) SyncKeyBindings(ctx context.Context) error {
|
|||||||
|
|
||||||
// GetKeyBindings 根据类型获取快捷键
|
// GetKeyBindings 根据类型获取快捷键
|
||||||
func (s *KeyBindingService) GetKeyBindings(ctx context.Context, kbType models.KeyBindingType) ([]*ent.KeyBinding, error) {
|
func (s *KeyBindingService) GetKeyBindings(ctx context.Context, kbType models.KeyBindingType) ([]*ent.KeyBinding, error) {
|
||||||
if kbType == models.Standard {
|
// 获取启用的扩展名称集合
|
||||||
// Standard 模式:只返回 type=standard 且 enabled=true
|
enabledExts, err := s.db.Client.Extension.Query().
|
||||||
return s.db.Client.KeyBinding.Query().
|
Where(extension.Enabled(true)).
|
||||||
Where(
|
|
||||||
keybinding.Type(string(kbType)),
|
|
||||||
keybinding.Enabled(true),
|
|
||||||
).
|
|
||||||
All(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emacs 模式:获取所有 enabled=true 的快捷键
|
|
||||||
allEnabled, err := s.db.Client.KeyBinding.Query().
|
|
||||||
Where(keybinding.Enabled(true)).
|
|
||||||
All(ctx)
|
All(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("query enabled key bindings error: %w", err)
|
return nil, fmt.Errorf("query enabled extensions error: %w", err)
|
||||||
|
}
|
||||||
|
enabledExtMap := make(map[string]bool, len(enabledExts))
|
||||||
|
for _, ext := range enabledExts {
|
||||||
|
enabledExtMap[ext.Name] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if kbType == models.Standard {
|
||||||
|
// Standard 模式:返回扩展已启用的快捷键
|
||||||
|
bindings, err := s.db.Client.KeyBinding.Query().
|
||||||
|
Where(keybinding.Type(string(kbType))).
|
||||||
|
Order(ent.Asc(keybinding.FieldID)).
|
||||||
|
All(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return filterByExtension(bindings, enabledExtMap), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emacs 模式:获取所有快捷键
|
||||||
|
allBindings, err := s.db.Client.KeyBinding.Query().
|
||||||
|
Order(ent.Asc(keybinding.FieldID)).
|
||||||
|
All(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("query key bindings error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建 emacs 快捷键的 name 集合
|
// 构建 emacs 快捷键的 name 集合
|
||||||
emacsNames := make(map[string]bool)
|
emacsNames := make(map[string]bool)
|
||||||
for _, kb := range allEnabled {
|
for _, kb := range allBindings {
|
||||||
if kb.Type == string(models.Emacs) {
|
if kb.Type == string(models.Emacs) {
|
||||||
emacsNames[kb.Name] = true
|
emacsNames[kb.Name] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 过滤:去掉与 emacs 冲突的 standard 快捷键
|
// 过滤:去掉与 emacs 冲突的 standard 快捷键,并过滤扩展未启用的
|
||||||
var result []*ent.KeyBinding
|
var result []*ent.KeyBinding
|
||||||
for _, kb := range allEnabled {
|
for _, kb := range allBindings {
|
||||||
// 如果是 standard 类型,且与 emacs 有 name 冲突,则跳过
|
|
||||||
if kb.Type == string(models.Standard) && emacsNames[kb.Name] {
|
if kb.Type == string(models.Standard) && emacsNames[kb.Name] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// editor 扩展始终包含,不检查启用状态
|
||||||
|
if kb.Extension != models.DefaultExtension && !enabledExtMap[kb.Extension] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
result = append(result, kb)
|
result = append(result, kb)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filterByExtension 过滤出扩展已启用的快捷键
|
||||||
|
func filterByExtension(bindings []*ent.KeyBinding, enabledExtMap map[string]bool) []*ent.KeyBinding {
|
||||||
|
result := make([]*ent.KeyBinding, 0, len(bindings))
|
||||||
|
for _, kb := range bindings {
|
||||||
|
// editor 扩展始终包含,不检查启用状态
|
||||||
|
if kb.Extension == models.DefaultExtension || enabledExtMap[kb.Extension] {
|
||||||
|
result = append(result, kb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// GetKeyBindingByID 根据ID获取快捷键
|
// GetKeyBindingByID 根据ID获取快捷键
|
||||||
func (s *KeyBindingService) GetKeyBindingByID(ctx context.Context, id int) (*ent.KeyBinding, error) {
|
func (s *KeyBindingService) GetKeyBindingByID(ctx context.Context, id int) (*ent.KeyBinding, error) {
|
||||||
kb, err := s.db.Client.KeyBinding.Get(ctx, id)
|
kb, err := s.db.Client.KeyBinding.Get(ctx, id)
|
||||||
@@ -163,7 +193,7 @@ func (s *KeyBindingService) GetKeyBindingByID(ctx context.Context, id int) (*ent
|
|||||||
return kb, nil
|
return kb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateKeyBindingKeys 更新快捷键绑定(根据操作系统自动判断更新哪个字段)
|
// UpdateKeyBindingKeys 更新快捷键绑定
|
||||||
func (s *KeyBindingService) UpdateKeyBindingKeys(ctx context.Context, id int, key string) error {
|
func (s *KeyBindingService) UpdateKeyBindingKeys(ctx context.Context, id int, key string) error {
|
||||||
kb, err := s.GetKeyBindingByID(ctx, id)
|
kb, err := s.GetKeyBindingByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -204,6 +234,20 @@ func (s *KeyBindingService) UpdateKeyBindingEnabled(ctx context.Context, id int,
|
|||||||
Exec(ctx)
|
Exec(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateKeyBindingPreventDefault 更新快捷键 PreventDefault 状态
|
||||||
|
func (s *KeyBindingService) UpdateKeyBindingPreventDefault(ctx context.Context, id int, preventDefault bool) error {
|
||||||
|
kb, err := s.GetKeyBindingByID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if kb == nil {
|
||||||
|
return fmt.Errorf("key binding not found: id=%d", id)
|
||||||
|
}
|
||||||
|
return s.db.Client.KeyBinding.UpdateOneID(kb.ID).
|
||||||
|
SetPreventDefault(preventDefault).
|
||||||
|
Exec(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
// GetDefaultKeyBindings 获取默认快捷键配置
|
// GetDefaultKeyBindings 获取默认快捷键配置
|
||||||
func (s *KeyBindingService) GetDefaultKeyBindings() []models.KeyBinding {
|
func (s *KeyBindingService) GetDefaultKeyBindings() []models.KeyBinding {
|
||||||
return models.NewDefaultKeyBindings()
|
return models.NewDefaultKeyBindings()
|
||||||
|
|||||||