clay-server 5.5.0-beta.4 → 5.5.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/github-connection-store.js +39 -0
- package/lib/github-runtime.js +43 -0
- package/lib/project-github-connection.js +164 -0
- package/lib/project-split-views.js +3 -1
- package/lib/project-view-workspace.js +10 -1
- package/lib/project.js +8 -0
- package/lib/public/appearance-bootstrap.js +6 -0
- package/lib/public/css/chrome-material.css +133 -0
- package/lib/public/css/menus.css +1 -17
- package/lib/public/css/navigation-island.css +261 -0
- package/lib/public/css/notifications-center.css +1 -17
- package/lib/public/css/settings-ui.css +8 -2
- package/lib/public/css/shared-browser.css +1 -18
- package/lib/public/css/split-view-layout.css +9 -5
- package/lib/public/css/sticky-notes.css +1 -18
- package/lib/public/css/title-bar.css +1 -1
- package/lib/public/css/workspace-background-gallery.css +43 -0
- package/lib/public/css/you.css +13 -10
- package/lib/public/index.html +53 -46
- package/lib/public/modules/app-messages.js +5 -0
- package/lib/public/modules/appearance-preferences.js +81 -0
- package/lib/public/modules/context-sources.js +2 -282
- package/lib/public/modules/github-mark.js +2 -0
- package/lib/public/modules/pane-appearance-bridge.js +9 -1
- package/lib/public/modules/pane-header-tooltips.js +36 -9
- package/lib/public/modules/personal-email-editor.js +305 -0
- package/lib/public/modules/personal-integration-editor.js +70 -0
- package/lib/public/modules/personal-settings-dialog.js +15 -1
- package/lib/public/modules/session-list-material.js +25 -0
- package/lib/public/modules/sidebar-collapse-focus.js +22 -0
- package/lib/public/modules/sidebar-sessions.js +2 -0
- package/lib/public/modules/sidebar.js +9 -10
- package/lib/public/modules/split-pane-renderer.js +5 -5
- package/lib/public/modules/split-view-shell-controls.js +9 -5
- package/lib/public/modules/split-view.js +2 -2
- package/lib/public/modules/theme.js +10 -28
- package/lib/public/modules/tool-pane-chrome.js +4 -1
- package/lib/public/modules/tool-pane-material.js +23 -0
- package/lib/public/modules/tooltip.js +7 -3
- package/lib/public/modules/tui-attention.js +9 -4
- package/lib/public/modules/user-settings-account.js +10 -1
- package/lib/public/modules/user-settings-github.js +176 -0
- package/lib/public/modules/user-settings-integrations.js +23 -12
- package/lib/public/modules/user-settings-layout.js +5 -3
- package/lib/public/modules/user-settings-themes.js +6 -2
- package/lib/public/modules/user-settings.js +2 -1
- package/lib/public/modules/view-presentation-state.js +2 -0
- package/lib/public/modules/workspace-background-gallery.js +92 -0
- package/lib/public/modules/workspace-custom-colors.js +132 -0
- package/lib/public/modules/you-activity.js +4 -2
- package/lib/public/pane-assets/app-BNMUDWD5.js +1 -0
- package/lib/public/pane-assets/chunk-3EA7GMQB.js +1 -0
- package/lib/public/pane-assets/chunk-4FKXTJ6O.js +1 -0
- package/lib/public/pane-assets/chunk-4WIT6JEU.js +1 -0
- package/lib/public/pane-assets/chunk-A5YYSG4B.js +1 -0
- package/lib/public/pane-assets/{chunk-SGMEO3P7.js → chunk-AF5TDQTT.js} +1 -1
- package/lib/public/pane-assets/{chunk-4WYURTPH.js → chunk-B4JTSONS.js} +1 -1
- package/lib/public/pane-assets/chunk-D2BDBUG5.js +2 -0
- package/lib/public/pane-assets/chunk-EGCR2MH4.js +1 -0
- package/lib/public/pane-assets/{chunk-FB5B2WYF.js → chunk-ENPPQJSX.js} +1 -1
- package/lib/public/pane-assets/chunk-ENWMPEO2.js +1 -0
- package/lib/public/pane-assets/{chunk-53KRXJDL.js → chunk-FA454EFE.js} +1 -1
- package/lib/public/pane-assets/chunk-FDZ37JGF.js +174 -0
- package/lib/public/pane-assets/{chunk-TU3AHPSN.js → chunk-FWEHZLDA.js} +1 -1
- package/lib/public/pane-assets/chunk-HY74JLC5.js +1 -0
- package/lib/public/pane-assets/{chunk-AMZ7P526.js → chunk-LH46GC2K.js} +1 -1
- package/lib/public/pane-assets/chunk-PDHV6Q3E.js +1 -0
- package/lib/public/pane-assets/chunk-Q2HJ5CWT.js +1 -0
- package/lib/public/pane-assets/chunk-SQC7XIGG.js +1 -0
- package/lib/public/pane-assets/chunk-TIEOZRO2.js +1 -0
- package/lib/public/pane-assets/chunk-U3KC4P2F.js +1 -0
- package/lib/public/pane-assets/{chunk-X45WI2U7.js → chunk-ULGL2YFP.js} +1 -1
- package/lib/public/pane-assets/chunk-W3KJANR2.js +1 -0
- package/lib/public/pane-assets/{chunk-UVTS6GUM.js → chunk-WI3BTTUY.js} +1 -1
- package/lib/public/pane-assets/{chunk-JIV7O5GN.js → chunk-YHBTK56T.js} +1 -1
- package/lib/public/pane-assets/{chunk-TK446XFF.js → chunk-YXTZSYUM.js} +1 -1
- package/lib/public/pane-assets/chunk-ZY4WB3PH.js +1 -0
- package/lib/public/pane-assets/manifest.json +424 -410
- package/lib/public/pane-assets/style-F4MQRRX2.css +1 -0
- package/lib/public/style.css +4 -0
- package/lib/public/workspace-art/workshop-dark.webp +0 -0
- package/lib/public/workspace-art/workshop-light.webp +0 -0
- package/lib/public/workspace-background-catalog.js +40 -0
- package/lib/server-appearance-settings.js +16 -5
- package/lib/server.js +6 -0
- package/lib/session-github.js +1 -7
- package/lib/terminal-manager.js +5 -1
- package/lib/terminal.js +10 -1
- package/package.json +1 -1
- package/lib/public/pane-assets/app-PV3SEOTX.js +0 -1
- package/lib/public/pane-assets/chunk-2G6DB3ES.js +0 -1
- package/lib/public/pane-assets/chunk-6QFLYOVY.js +0 -1
- package/lib/public/pane-assets/chunk-BK2NRZFM.js +0 -1
- package/lib/public/pane-assets/chunk-D3WR2TYZ.js +0 -2
- package/lib/public/pane-assets/chunk-E7D5A27I.js +0 -1
- package/lib/public/pane-assets/chunk-FDBSE7BE.js +0 -174
- package/lib/public/pane-assets/chunk-FHB76KH2.js +0 -1
- package/lib/public/pane-assets/chunk-FNGO6432.js +0 -1
- package/lib/public/pane-assets/chunk-HF7AK56Q.js +0 -1
- package/lib/public/pane-assets/chunk-ILVRGTDF.js +0 -1
- package/lib/public/pane-assets/chunk-L3SFMSLP.js +0 -1
- package/lib/public/pane-assets/chunk-PAY3A4JS.js +0 -1
- package/lib/public/pane-assets/chunk-QVHC324H.js +0 -1
- package/lib/public/pane-assets/chunk-SFANEWZA.js +0 -1
- package/lib/public/pane-assets/chunk-US5VELGB.js +0 -1
- package/lib/public/pane-assets/chunk-VZ2OKDAO.js +0 -1
- package/lib/public/pane-assets/style-563D4UN6.css +0 -1
|
@@ -1,24 +1,50 @@
|
|
|
1
|
-
// Pane chrome
|
|
1
|
+
// Pane chrome and Worker viewers share the existing delegated tooltip service.
|
|
2
2
|
import { registerTooltip, pruneTooltip } from './tooltip.js';
|
|
3
3
|
|
|
4
|
-
var HEADERS = '.split-pane-header, .tool-pane-header, .file-viewer-tabbar, .terminal-header, .shared-browser-header, .split-view-workers, #top-bar .top-bar-actions';
|
|
4
|
+
var HEADERS = '.split-pane-header, .tool-pane-header, .file-viewer-tabbar, .terminal-header, .shared-browser-header, .split-view-workers, #top-bar .top-bar-actions, #split-view-worker-popover, body.worker-pane-locked #messages, body.worker-pane-locked #input-area';
|
|
5
|
+
var labels = new WeakMap();
|
|
5
6
|
function sync(header) {
|
|
6
|
-
header.querySelectorAll('[
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (
|
|
7
|
+
if (header.id === 'split-view-worker-popover' || header.id === 'messages') header.querySelectorAll('.tool-header[role="button"], .tool-group-header[role="button"]').forEach(function (element) {
|
|
8
|
+
if (element.hasAttribute('aria-label') && element.dataset.tooltipDisclosure !== 'true') return;
|
|
9
|
+
var name = element.querySelector('.tool-name, .tool-group-label');
|
|
10
|
+
if (!name) return;
|
|
11
|
+
element.dataset.tooltipDisclosure = 'true';
|
|
12
|
+
var label = (element.getAttribute('aria-expanded') === 'true' ? 'Hide ' : 'Show ') + name.textContent + ' details';
|
|
13
|
+
if (element.getAttribute('aria-label') !== label) element.setAttribute('aria-label', label);
|
|
14
|
+
});
|
|
15
|
+
// Move icon-owned native hints to the operable control before removing them.
|
|
16
|
+
header.querySelectorAll('[title], svg title').forEach(function (element) {
|
|
17
|
+
var control = element.closest('button, [role="button"], a, [role="img"]');
|
|
18
|
+
if (!control && element.matches('svg title')) control = element.parentElement;
|
|
19
|
+
if (!control || control === element) return;
|
|
20
|
+
var label = element.getAttribute('title') || element.textContent;
|
|
21
|
+
if (label && !control.hasAttribute('title') && !control.hasAttribute('data-tip') && !control.hasAttribute('aria-label')) control.setAttribute('title', label);
|
|
22
|
+
if (element.matches('svg title')) element.remove(); else element.removeAttribute('title');
|
|
23
|
+
});
|
|
24
|
+
(header.matches('[title], [data-tip]') ? [header] : []).concat(Array.from(header.querySelectorAll('[title], button, [role="button"], a[aria-label], [data-tip]'))).forEach(function (element) {
|
|
25
|
+
var previous = labels.get(element), tip = element.getAttribute('data-tip'), title = element.getAttribute('title');
|
|
26
|
+
var explicit = tip && (!previous || previous.explicit || tip !== previous.tip);
|
|
27
|
+
var aria = element.getAttribute('aria-label');
|
|
28
|
+
if (previous && aria && previous.aria !== aria) delete element.dataset.tooltipGeneratedLabel;
|
|
29
|
+
var label = explicit ? tip : title || (previous && previous.source === 'title' ? tip : aria || tip);
|
|
30
|
+
if (!label || !label.trim()) { element.removeAttribute('title'); return; }
|
|
31
|
+
if (element.matches('button, [role="button"], a') && (!element.hasAttribute('aria-label') || element.dataset.tooltipGeneratedLabel === 'true' && title)) {
|
|
10
32
|
element.dataset.tooltipGeneratedLabel = 'true';
|
|
11
33
|
if (element.getAttribute('aria-label') !== label) element.setAttribute('aria-label', label);
|
|
12
34
|
}
|
|
13
|
-
if (
|
|
35
|
+
if (tip !== label || element.hasAttribute('title')) registerTooltip(element, label);
|
|
36
|
+
labels.set(element, { tip: label, explicit: !!explicit, aria: element.getAttribute('aria-label'), source: title ? 'title' : previous && previous.source || 'aria' });
|
|
14
37
|
});
|
|
15
38
|
}
|
|
16
39
|
export function initPaneHeaderTooltips() {
|
|
17
40
|
document.querySelectorAll(HEADERS).forEach(sync);
|
|
18
41
|
var observer = new MutationObserver(function (records) {
|
|
19
|
-
pruneTooltip();
|
|
20
42
|
var headers = new Set();
|
|
21
43
|
records.forEach(function (record) {
|
|
44
|
+
if (record.type === 'attributes' && (record.attributeName === 'class' || record.attributeName === 'hidden')) {
|
|
45
|
+
if (record.target === document.body) document.querySelectorAll('body.worker-pane-locked #messages, body.worker-pane-locked #input-area').forEach(function (root) { headers.add(root); });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
22
48
|
var parent = record.target.nodeType === 1 && record.target.closest(HEADERS); if (parent) headers.add(parent);
|
|
23
49
|
(record.addedNodes || []).forEach(function (node) {
|
|
24
50
|
if (node.nodeType !== 1) return;
|
|
@@ -27,6 +53,7 @@ export function initPaneHeaderTooltips() {
|
|
|
27
53
|
});
|
|
28
54
|
});
|
|
29
55
|
headers.forEach(function (header) { if (header.isConnected) sync(header); });
|
|
56
|
+
pruneTooltip();
|
|
30
57
|
});
|
|
31
|
-
observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['title', 'aria-label'] });
|
|
58
|
+
observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['title', 'aria-label', 'data-tip', 'aria-expanded', 'hidden', 'class'] });
|
|
32
59
|
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { getWs } from './ws-ref.js';
|
|
3
|
+
import { showToast } from './utils.js';
|
|
4
|
+
import { preparePersonalConnectionDialog, closePersonalEmailEditor } from './personal-settings-dialog.js';
|
|
5
|
+
import { selectIntegrationEditor } from './personal-integration-editor.js';
|
|
6
|
+
|
|
7
|
+
function settleEmailRequest() {
|
|
8
|
+
store.set({personalEmailSaving:false});
|
|
9
|
+
document.querySelectorAll('#email-setup-modal input, #email-setup-modal button').forEach(function (el) { el.disabled = false; });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function showEmailSetupModal(provider, host) {
|
|
13
|
+
if (host) {
|
|
14
|
+
selectIntegrationEditor('email-add:' + provider, '#email-setup-modal', function () { openEmailSetup(provider, host); });
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
openEmailSetup(provider, host);
|
|
18
|
+
}
|
|
19
|
+
function openEmailSetup(provider, host) {
|
|
20
|
+
var providerNames = { gmail: "Gmail", outlook: "Outlook Mail", yahoo: "Yahoo Mail", custom: "Custom email" };
|
|
21
|
+
if (!Object.hasOwn(providerNames, provider)) provider = null;
|
|
22
|
+
// Remove any existing modal
|
|
23
|
+
var existing = document.getElementById("email-setup-modal");
|
|
24
|
+
if (existing) {existing.querySelector("input:not([type=hidden]),button").focus();return;}
|
|
25
|
+
|
|
26
|
+
var overlay = document.createElement("div");
|
|
27
|
+
overlay.id = "email-setup-modal";
|
|
28
|
+
overlay.className = host ? "email-setup-inline" : "email-setup-overlay";
|
|
29
|
+
|
|
30
|
+
if (!provider) {
|
|
31
|
+
var picker = document.createElement('div'); picker.className = 'email-setup-dialog';
|
|
32
|
+
picker.innerHTML = '<h3>Choose an email provider</h3><div class="us-integration-tiles"></div><button id="email-setup-cancel" type="button" class="email-setup-btn">Cancel</button>';
|
|
33
|
+
Object.keys(providerNames).forEach(function (id) {
|
|
34
|
+
var button = document.createElement('button'); button.type = 'button'; button.className = 'email-setup-btn'; button.textContent = providerNames[id];
|
|
35
|
+
button.onclick = function () { closePicker(); showEmailSetupModal(id, host); };
|
|
36
|
+
picker.querySelector('.us-integration-tiles').appendChild(button);
|
|
37
|
+
});
|
|
38
|
+
overlay.appendChild(picker); (host || document.body).appendChild(overlay); var closePicker = preparePersonalConnectionDialog(overlay, !!host); return;
|
|
39
|
+
}
|
|
40
|
+
var modal = document.createElement("div");
|
|
41
|
+
modal.className = "email-setup-dialog";
|
|
42
|
+
modal.innerHTML =
|
|
43
|
+
'<h3 class="email-setup-title">Add ' + providerNames[provider] + ' account</h3>' +
|
|
44
|
+
'<input type="hidden" id="email-setup-provider" value="' + provider + '">' +
|
|
45
|
+
'<div class="email-setup-field">' +
|
|
46
|
+
'<label class="email-setup-label">Email Address</label>' +
|
|
47
|
+
'<input id="email-setup-address" type="email" placeholder="you@example.com" class="email-setup-input" />' +
|
|
48
|
+
'</div>' +
|
|
49
|
+
'<div class="email-setup-field">' +
|
|
50
|
+
'<label class="email-setup-label">App Password</label>' +
|
|
51
|
+
'<div class="email-setup-password-wrap">' +
|
|
52
|
+
'<input id="email-setup-password" type="password" placeholder="xxxx-xxxx-xxxx-xxxx" class="email-setup-input" />' +
|
|
53
|
+
'<button id="email-setup-password-toggle" type="button" class="email-setup-password-eye" title="Show password"><i data-lucide="eye"></i></button>' +
|
|
54
|
+
'</div>' +
|
|
55
|
+
'<a id="email-setup-help" href="https://support.google.com/accounts/answer/185833" target="_blank" rel="noopener" class="email-setup-help">How to create an App Password</a>' +
|
|
56
|
+
'</div>' +
|
|
57
|
+
'<div id="email-setup-custom-fields" style="display:none;">' +
|
|
58
|
+
'<div class="email-setup-field">' +
|
|
59
|
+
'<label class="email-setup-label">IMAP Host</label>' +
|
|
60
|
+
'<div class="email-setup-row">' +
|
|
61
|
+
'<input id="email-setup-imap-host" type="text" placeholder="imap.example.com" class="email-setup-input" style="flex:1;" />' +
|
|
62
|
+
'<input id="email-setup-imap-port" type="number" value="993" class="email-setup-input email-setup-port" />' +
|
|
63
|
+
'</div>' +
|
|
64
|
+
'</div>' +
|
|
65
|
+
'<div class="email-setup-field">' +
|
|
66
|
+
'<label class="email-setup-label">SMTP Host</label>' +
|
|
67
|
+
'<div class="email-setup-row">' +
|
|
68
|
+
'<input id="email-setup-smtp-host" type="text" placeholder="smtp.example.com" class="email-setup-input" style="flex:1;" />' +
|
|
69
|
+
'<input id="email-setup-smtp-port" type="number" value="587" class="email-setup-input email-setup-port" />' +
|
|
70
|
+
'</div>' +
|
|
71
|
+
'</div>' +
|
|
72
|
+
'</div>' +
|
|
73
|
+
'<div id="email-setup-status" class="email-setup-status"></div>' +
|
|
74
|
+
'<div class="email-setup-actions">' +
|
|
75
|
+
'<button id="email-setup-test" type="button" class="email-setup-btn email-setup-btn-secondary">Test Connection</button>' +
|
|
76
|
+
'<button id="email-setup-cancel" type="button" class="email-setup-btn email-setup-btn-ghost">Cancel</button>' +
|
|
77
|
+
'<button id="email-setup-save" type="button" class="email-setup-btn email-setup-btn-primary">Add Account</button>' +
|
|
78
|
+
'</div>';
|
|
79
|
+
|
|
80
|
+
overlay.appendChild(modal);
|
|
81
|
+
(host || document.body).appendChild(overlay);
|
|
82
|
+
preparePersonalConnectionDialog(overlay, !!host);
|
|
83
|
+
|
|
84
|
+
// Event: close on overlay click
|
|
85
|
+
overlay.addEventListener("click", function (e) {
|
|
86
|
+
if (!host && e.target === overlay) overlay.remove();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Event: cancel button
|
|
90
|
+
document.getElementById("email-setup-cancel").addEventListener("click", function () {
|
|
91
|
+
overlay.remove();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Event: password visibility toggle
|
|
95
|
+
var pwInput = document.getElementById("email-setup-password");
|
|
96
|
+
var pwToggle = document.getElementById("email-setup-password-toggle");
|
|
97
|
+
pwToggle.addEventListener("click", function () {
|
|
98
|
+
var isHidden = pwInput.type === "password";
|
|
99
|
+
pwInput.type = isHidden ? "text" : "password";
|
|
100
|
+
pwToggle.innerHTML = isHidden ? '<i data-lucide="eye-off"></i>' : '<i data-lucide="eye"></i>';
|
|
101
|
+
pwToggle.title = isHidden ? "Hide password" : "Show password";
|
|
102
|
+
if (typeof lucide !== "undefined") lucide.createIcons();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Event: provider change
|
|
106
|
+
var providerSelect = document.getElementById("email-setup-provider");
|
|
107
|
+
var helpLink = document.getElementById("email-setup-help");
|
|
108
|
+
var customFields = document.getElementById("email-setup-custom-fields");
|
|
109
|
+
|
|
110
|
+
// Provider presets only configure IMAP/SMTP infra and the help link.
|
|
111
|
+
// The user always enters their full email address (e.g. user@company.com),
|
|
112
|
+
// so Google Workspace / Microsoft 365 accounts on custom domains work too.
|
|
113
|
+
var providerMeta = {
|
|
114
|
+
gmail: {
|
|
115
|
+
helpUrl: "https://support.google.com/accounts/answer/185833",
|
|
116
|
+
},
|
|
117
|
+
outlook: {
|
|
118
|
+
helpUrl: "https://support.microsoft.com/en-us/account-billing/using-app-passwords-with-apps-that-don-t-support-two-step-verification-5896ed9b-4263-e681-128a-a6f2979a7944",
|
|
119
|
+
},
|
|
120
|
+
yahoo: {
|
|
121
|
+
helpUrl: "https://help.yahoo.com/kb/generate-manage-third-party-passwords-sln15241.html",
|
|
122
|
+
},
|
|
123
|
+
custom: {
|
|
124
|
+
helpUrl: null,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
var emailInput = document.getElementById("email-setup-address");
|
|
129
|
+
|
|
130
|
+
function applyProviderMeta(val) {
|
|
131
|
+
var meta = providerMeta[val] || providerMeta.custom;
|
|
132
|
+
customFields.style.display = val === "custom" ? "block" : "none";
|
|
133
|
+
if (meta.helpUrl) {
|
|
134
|
+
helpLink.href = meta.helpUrl;
|
|
135
|
+
helpLink.style.display = "";
|
|
136
|
+
} else {
|
|
137
|
+
helpLink.style.display = "none";
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
applyProviderMeta(provider);
|
|
142
|
+
|
|
143
|
+
// Reset test state
|
|
144
|
+
store.set({personalEmailTestPassed:false});
|
|
145
|
+
store.set({personalEmailPendingSave:false});
|
|
146
|
+
|
|
147
|
+
// Reset test status when inputs change
|
|
148
|
+
function onInputChange() {
|
|
149
|
+
store.set({personalEmailTestPassed:false});
|
|
150
|
+
store.set({personalEmailPendingSave:false});
|
|
151
|
+
var saveBtn = document.getElementById("email-setup-save");
|
|
152
|
+
if (saveBtn) saveBtn.textContent = "Add Account";
|
|
153
|
+
}
|
|
154
|
+
overlay.addEventListener('input', onInputChange);
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
function runTest() {
|
|
158
|
+
var statusEl = document.getElementById("email-setup-status");
|
|
159
|
+
var emailAddr = getFullEmail();
|
|
160
|
+
var appPass = document.getElementById("email-setup-password").value;
|
|
161
|
+
|
|
162
|
+
if (!emailAddr || emailAddr.indexOf("@") === -1 || !appPass) {
|
|
163
|
+
statusEl.style.display = "block";
|
|
164
|
+
statusEl.style.color = "var(--error, #e74c3c)";
|
|
165
|
+
statusEl.textContent = "Email and app password are required.";
|
|
166
|
+
store.set({personalEmailPendingSave:false});
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
statusEl.style.display = "block";
|
|
171
|
+
statusEl.style.color = "var(--text-muted)";
|
|
172
|
+
statusEl.textContent = "Testing connection...";
|
|
173
|
+
|
|
174
|
+
var msgData = buildEmailSetupData();
|
|
175
|
+
msgData.type = "email_account_test";
|
|
176
|
+
|
|
177
|
+
var ws = getWs();
|
|
178
|
+
if (ws && ws.readyState === 1) {
|
|
179
|
+
store.set({personalEmailSaving:true,personalEmailRequestOwner:store.get('myUserId'),personalEmailRequestSocket:store.get('projectSplitViewSocketGeneration')});
|
|
180
|
+
document.querySelectorAll('#email-setup-modal input, #email-setup-modal button').forEach(function (el) { el.disabled = true; });
|
|
181
|
+
ws.send(JSON.stringify(msgData));
|
|
182
|
+
} else {
|
|
183
|
+
store.set({personalEmailPendingSave:false});
|
|
184
|
+
statusEl.textContent = 'Disconnected. Reconnect and retry.';
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Event: test connection
|
|
189
|
+
document.getElementById("email-setup-test").addEventListener("click", function () {
|
|
190
|
+
store.set({personalEmailPendingSave:false});
|
|
191
|
+
runTest();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Event: save (requires test to pass first)
|
|
195
|
+
document.getElementById("email-setup-save").addEventListener("click", function () {
|
|
196
|
+
if (store.get('personalEmailTestPassed')) {
|
|
197
|
+
// Test already passed, proceed with save
|
|
198
|
+
doSave();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Run test first, then auto-save on success
|
|
202
|
+
store.set({personalEmailPendingSave:true});
|
|
203
|
+
var saveBtn = document.getElementById("email-setup-save");
|
|
204
|
+
if (saveBtn) saveBtn.textContent = "Testing...";
|
|
205
|
+
runTest();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function doSave() {
|
|
211
|
+
var statusEl = document.getElementById("email-setup-status");
|
|
212
|
+
statusEl.style.display = "block";
|
|
213
|
+
statusEl.style.color = "var(--text-muted)";
|
|
214
|
+
statusEl.textContent = "Adding account...";
|
|
215
|
+
|
|
216
|
+
var msgData = buildEmailSetupData();
|
|
217
|
+
msgData.type = "email_account_add";
|
|
218
|
+
|
|
219
|
+
var ws = getWs();
|
|
220
|
+
if (ws && ws.readyState === 1) {
|
|
221
|
+
store.set({personalEmailSaving:true,personalEmailRequestOwner:store.get('myUserId'),personalEmailRequestSocket:store.get('projectSplitViewSocketGeneration')});
|
|
222
|
+
document.querySelectorAll('#email-setup-modal input, #email-setup-modal button').forEach(function (el) { el.disabled = true; });
|
|
223
|
+
ws.send(JSON.stringify(msgData));
|
|
224
|
+
} else {
|
|
225
|
+
store.set({personalEmailPendingSave:false});
|
|
226
|
+
statusEl.textContent = 'Disconnected. Reconnect and retry.';
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function getFullEmail() {
|
|
231
|
+
return document.getElementById("email-setup-address").value.trim();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function buildEmailSetupData() {
|
|
235
|
+
var provider = document.getElementById("email-setup-provider").value;
|
|
236
|
+
var email = getFullEmail();
|
|
237
|
+
var appPassword = document.getElementById("email-setup-password").value;
|
|
238
|
+
var data = { provider: provider, email: email, appPassword: appPassword };
|
|
239
|
+
|
|
240
|
+
if (provider === "custom") {
|
|
241
|
+
data.imap = {
|
|
242
|
+
host: document.getElementById("email-setup-imap-host").value.trim(),
|
|
243
|
+
port: parseInt(document.getElementById("email-setup-imap-port").value, 10) || 993,
|
|
244
|
+
tls: true,
|
|
245
|
+
};
|
|
246
|
+
data.smtp = {
|
|
247
|
+
host: document.getElementById("email-setup-smtp-host").value.trim(),
|
|
248
|
+
port: parseInt(document.getElementById("email-setup-smtp-port").value, 10) || 587,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
return data;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Handle email_account_test_result from server
|
|
255
|
+
export function handleEmailTestResult(msg) {
|
|
256
|
+
var statusEl = document.getElementById("email-setup-status");
|
|
257
|
+
if (!statusEl || !store.get('personalEmailSaving') || store.get('personalEmailRequestOwner') !== store.get('myUserId') || store.get('personalEmailRequestSocket') !== store.get('projectSplitViewSocketGeneration')) return;
|
|
258
|
+
var saveBtn = document.getElementById("email-setup-save");
|
|
259
|
+
settleEmailRequest();
|
|
260
|
+
|
|
261
|
+
statusEl.style.display = "block";
|
|
262
|
+
if (msg.ok) {
|
|
263
|
+
store.set({personalEmailTestPassed:true});
|
|
264
|
+
if (store.get('personalEmailPendingSave')) {
|
|
265
|
+
// Test passed from Add Account click, proceed to save
|
|
266
|
+
store.set({personalEmailPendingSave:false});
|
|
267
|
+
doSave();
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
statusEl.style.color = "var(--success, #2ecc71)";
|
|
271
|
+
statusEl.textContent = "Connection successful! IMAP and SMTP both working.";
|
|
272
|
+
} else {
|
|
273
|
+
store.set({personalEmailTestPassed:false});
|
|
274
|
+
store.set({personalEmailPendingSave:false});
|
|
275
|
+
if (saveBtn) saveBtn.textContent = "Add Account";
|
|
276
|
+
statusEl.style.color = "var(--error, #e74c3c)";
|
|
277
|
+
var parts = [];
|
|
278
|
+
if (msg.imap && !msg.imap.ok) parts.push("IMAP: " + (msg.imap.error || "failed"));
|
|
279
|
+
if (msg.smtp && !msg.smtp.ok) parts.push("SMTP: " + (msg.smtp.error || "failed"));
|
|
280
|
+
statusEl.textContent = parts.length > 0 ? parts.join("; ") : (msg.error || "Connection failed");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Handle email_account_add_result from server
|
|
285
|
+
export function handleEmailAddResult(msg) {
|
|
286
|
+
var statusEl = document.getElementById("email-setup-status");
|
|
287
|
+
if (!statusEl || !store.get('personalEmailSaving') || store.get('personalEmailRequestOwner') !== store.get('myUserId') || store.get('personalEmailRequestSocket') !== store.get('projectSplitViewSocketGeneration')) return;
|
|
288
|
+
settleEmailRequest();
|
|
289
|
+
|
|
290
|
+
statusEl.style.display = "block";
|
|
291
|
+
if (msg.ok) {
|
|
292
|
+
statusEl.style.color = "#2ecc71";
|
|
293
|
+
statusEl.textContent = "Account added successfully!";
|
|
294
|
+
closePersonalEmailEditor();
|
|
295
|
+
} else {
|
|
296
|
+
statusEl.style.color = "#e74c3c";
|
|
297
|
+
statusEl.textContent = msg.error || "Failed to add account.";
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Handle email_account_remove_result from server
|
|
302
|
+
export function handleEmailRemoveResult(msg) {
|
|
303
|
+
showToast(msg.ok ? 'Personal mailbox disconnected.' : msg.error || 'Could not disconnect mailbox. Retry from Email settings.');
|
|
304
|
+
// The acknowledged list arrives separately through email_accounts_list.
|
|
305
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { confirmSettingsAction } from './server-settings-state.js';
|
|
3
|
+
import { showToast } from './utils.js';
|
|
4
|
+
import { closePersonalLinearEditor } from './user-settings-integrations.js';
|
|
5
|
+
import { closeGithubEditor, stopGithubEditorLogin } from './user-settings-github.js';
|
|
6
|
+
import { closePersonalEmailEditor } from './personal-settings-dialog.js';
|
|
7
|
+
|
|
8
|
+
export function integrationEditorBusy() {
|
|
9
|
+
return store.get('personalLinearSaving') || store.get('personalEmailSaving') || store.get('personalIntegrationSwitching') ||
|
|
10
|
+
store.get('githubSettingsPending') && store.get('githubSettingsAction') !== 'get' && store.get('githubSettingsAction') !== 'login';
|
|
11
|
+
}
|
|
12
|
+
function focusEditor(selector) {
|
|
13
|
+
var root = document.querySelector(selector);
|
|
14
|
+
if (!root) return;
|
|
15
|
+
var last = store.get('personalIntegrationFocus');
|
|
16
|
+
var target = last && root.contains(last) ? last : root.querySelector('input:not([type=hidden]),button') || root;
|
|
17
|
+
if (target.disabled) { root.tabIndex = -1; target = root; }
|
|
18
|
+
target.focus();
|
|
19
|
+
}
|
|
20
|
+
export function clearIntegrationEditor(key) {
|
|
21
|
+
var active = store.get('personalIntegrationEditor');
|
|
22
|
+
if (active && active.key === key) store.set({personalIntegrationEditor:null,personalIntegrationFocus:null});
|
|
23
|
+
}
|
|
24
|
+
function cleanup() {
|
|
25
|
+
var active = store.get('personalIntegrationEditor');
|
|
26
|
+
if (!active) return;
|
|
27
|
+
if (active.key === 'github') closeGithubEditor();
|
|
28
|
+
else if (active.key.indexOf('linear:') === 0) closePersonalLinearEditor();
|
|
29
|
+
else if (active.key.indexOf('email-add:') === 0) closePersonalEmailEditor();
|
|
30
|
+
else {
|
|
31
|
+
var panel = document.querySelector(active.selector);
|
|
32
|
+
if (panel) { panel.hidden = true; panel.parentElement.querySelector('[aria-expanded]').setAttribute('aria-expanded','false'); }
|
|
33
|
+
}
|
|
34
|
+
clearIntegrationEditor(active.key);
|
|
35
|
+
}
|
|
36
|
+
export function selectIntegrationEditor(key, selector, open) {
|
|
37
|
+
if (integrationEditorBusy()) {
|
|
38
|
+
var current = store.get('personalIntegrationEditor');
|
|
39
|
+
if (current) focusEditor(current.selector);
|
|
40
|
+
showToast('Wait for the current connection operation to finish.'); return;
|
|
41
|
+
}
|
|
42
|
+
var active = store.get('personalIntegrationEditor');
|
|
43
|
+
if (active && active.key === key) { focusEditor(selector); return; }
|
|
44
|
+
var actor = store.get('myUserId'), socket = store.get('projectSplitViewSocketGeneration');
|
|
45
|
+
async function proceed() {
|
|
46
|
+
if (actor !== store.get('myUserId') || socket !== store.get('projectSplitViewSocketGeneration') || integrationEditorBusy()) return;
|
|
47
|
+
store.set({personalIntegrationSwitching:true});
|
|
48
|
+
try {
|
|
49
|
+
if (active && active.key === 'github' && !await stopGithubEditorLogin()) return;
|
|
50
|
+
if (actor !== store.get('myUserId') || socket !== store.get('projectSplitViewSocketGeneration') || active !== store.get('personalIntegrationEditor')) return;
|
|
51
|
+
cleanup();
|
|
52
|
+
if (!key) { if (open) open(); return; }
|
|
53
|
+
store.set({personalIntegrationEditor:{key:key,selector:selector}});
|
|
54
|
+
open();
|
|
55
|
+
} finally { store.set({personalIntegrationSwitching:false}); }
|
|
56
|
+
}
|
|
57
|
+
if (active && (store.get('personalLinearDirty') || store.get('personalEmailDirty'))) {
|
|
58
|
+
focusEditor(active.selector);
|
|
59
|
+
confirmSettingsAction('Discard this unsaved connection draft?', 'Discard', proceed);
|
|
60
|
+
} else proceed();
|
|
61
|
+
}
|
|
62
|
+
export function bindIntegrationEditorFocus(root) {
|
|
63
|
+
root.addEventListener('focusin', function (event) {
|
|
64
|
+
var active = store.get('personalIntegrationEditor'), editor = active && document.querySelector(active.selector);
|
|
65
|
+
if (editor && editor.contains(event.target)) store.set({personalIntegrationFocus:event.target});
|
|
66
|
+
});
|
|
67
|
+
store.subscribe(function (state, previous) {
|
|
68
|
+
if (state.myUserId !== previous.myUserId) store.set({personalIntegrationEditor:null,personalIntegrationFocus:null});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { selectIntegrationEditor, clearIntegrationEditor } from './personal-integration-editor.js';
|
|
1
2
|
import { store } from './store.js';
|
|
2
3
|
import { confirmSettingsAction, isolateSettingsDialog, trapSettingsFocus } from './server-settings-state.js';
|
|
3
4
|
import { enhanceSettingsSelects } from './settings-select.js';
|
|
@@ -31,10 +32,18 @@ export function preparePersonalConnectionDialog(overlay, inline) {
|
|
|
31
32
|
}) : function () {};
|
|
32
33
|
function cleanup() { observer.disconnect(); unsubscribe(); restore(); if (inline) store.set({personalEmailDirty:false}); }
|
|
33
34
|
function close() {
|
|
34
|
-
cleanup();
|
|
35
|
+
cleanup();
|
|
36
|
+
overlay.querySelectorAll('input,textarea').forEach(function (field) { field.value = ''; });
|
|
37
|
+
store.set({personalEmailSaving:false,personalEmailPendingSave:false,personalEmailTestPassed:false});
|
|
38
|
+
var active = store.get('personalIntegrationEditor');
|
|
39
|
+
if (inline && active && active.key.indexOf('email-add:') === 0) clearIntegrationEditor(active.key);
|
|
40
|
+
overlay.remove();
|
|
35
41
|
if (previous && previous.isConnected) previous.focus();
|
|
36
42
|
}
|
|
43
|
+
overlay.addEventListener('connection-close', close);
|
|
37
44
|
function leave() {
|
|
45
|
+
if (store.get('personalEmailSaving')) return;
|
|
46
|
+
if (inline) { selectIntegrationEditor(null, null); return; }
|
|
38
47
|
if (dirty) confirmSettingsAction('Discard this unsaved mailbox connection?', 'Discard', close);
|
|
39
48
|
else close();
|
|
40
49
|
}
|
|
@@ -55,3 +64,8 @@ export function preparePersonalConnectionDialog(overlay, inline) {
|
|
|
55
64
|
(overlay.querySelector('#email-setup-address') || overlay.querySelector('button')).focus();
|
|
56
65
|
return close;
|
|
57
66
|
}
|
|
67
|
+
|
|
68
|
+
export function closePersonalEmailEditor() {
|
|
69
|
+
var overlay = document.getElementById('email-setup-modal');
|
|
70
|
+
if (overlay) overlay.dispatchEvent(new Event('connection-close'));
|
|
71
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Keep a clear sticky toolbar over the sidebar's one glass surface. Clip only
|
|
2
|
+
// the scrolling content's paint, without changing its layout or scroll owner.
|
|
3
|
+
export function bindSessionListMaterial(list) {
|
|
4
|
+
var scroller = list.parentElement;
|
|
5
|
+
function measure() {
|
|
6
|
+
var toolbar = list.querySelector(':scope > .session-list-sticky-top');
|
|
7
|
+
if (!toolbar) return;
|
|
8
|
+
var bottom = toolbar.getBoundingClientRect().bottom;
|
|
9
|
+
Array.from(list.children).forEach(function (content) {
|
|
10
|
+
if (content === toolbar) return;
|
|
11
|
+
var overlap = Math.max(0, bottom - content.getBoundingClientRect().top);
|
|
12
|
+
content.style.setProperty('--session-list-clip-top', overlap + 'px');
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
if (!scroller.dataset.sessionListMaterial) {
|
|
16
|
+
scroller.dataset.sessionListMaterial = 'true';
|
|
17
|
+
scroller.addEventListener('scroll', measure, { passive: true });
|
|
18
|
+
if (typeof ResizeObserver === 'function') {
|
|
19
|
+
var observer = new ResizeObserver(measure);
|
|
20
|
+
observer.observe(scroller); observer.observe(list);
|
|
21
|
+
}
|
|
22
|
+
else window.addEventListener('resize', measure);
|
|
23
|
+
}
|
|
24
|
+
measure();
|
|
25
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Keep desktop focus on the navigation controls when one side disappears.
|
|
2
|
+
export function restoreSidebarCollapseFocus(collapsed, previous) {
|
|
3
|
+
if (!previous || document.body.classList.contains('pane-mode') || !window.matchMedia('(min-width: 769px)').matches) return;
|
|
4
|
+
var leaving = collapsed ? previous.closest('#sidebar-column, #mate-sidebar-column') :
|
|
5
|
+
previous.closest('#sidebar-shell-expand-btn, #sidebar-expand-btn, .split-pane-sidebar');
|
|
6
|
+
if (!leaving) return;
|
|
7
|
+
function restore(attempt) {
|
|
8
|
+
var layout = document.getElementById('layout');
|
|
9
|
+
if (!layout || layout.classList.contains('sidebar-collapsed') !== collapsed ||
|
|
10
|
+
!window.matchMedia('(min-width: 769px)').matches ||
|
|
11
|
+
document.activeElement !== previous && document.activeElement !== document.body) return;
|
|
12
|
+
var mate = document.getElementById('mate-sidebar-column');
|
|
13
|
+
var sidebar = mate && !mate.classList.contains('hidden') ? mate : document.getElementById('sidebar-column');
|
|
14
|
+
var target = collapsed ? document.getElementById('sidebar-shell-expand-btn') :
|
|
15
|
+
sidebar && sidebar.querySelector('.sidebar-collapse-btn');
|
|
16
|
+
var region = collapsed ? document.getElementById('navigation-island') : sidebar;
|
|
17
|
+
if (target && !target.hidden && region && region.getBoundingClientRect().width > 0 && target.getClientRects().length) {
|
|
18
|
+
target.focus({ preventScroll: true });
|
|
19
|
+
} else if (attempt < 3) requestAnimationFrame(function () { restore(attempt + 1); });
|
|
20
|
+
}
|
|
21
|
+
restore(0);
|
|
22
|
+
}
|
|
@@ -7,6 +7,7 @@ import { escapeHtml } from './utils.js';
|
|
|
7
7
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
8
8
|
import { openSearch as openSessionSearch } from './session-search.js';
|
|
9
9
|
import { store } from './store.js';
|
|
10
|
+
import { bindSessionListMaterial } from './session-list-material.js';
|
|
10
11
|
import { getWs } from './ws-ref.js';
|
|
11
12
|
import { getSessionListEl } from './dom-refs.js';
|
|
12
13
|
import { dismissOverlayPanels, closeSidebar, updatePageTitle, spawnDustParticles } from './sidebar.js';
|
|
@@ -1134,6 +1135,7 @@ export function renderSessionList(sessions) {
|
|
|
1134
1135
|
regularContainer.appendChild(renderFavoritesSection(layout, folderCtx));
|
|
1135
1136
|
renderOrdinarySections(layout, folderCtx, regularContainer);
|
|
1136
1137
|
getSessionListEl().appendChild(regularContainer);
|
|
1138
|
+
bindSessionListMaterial(getSessionListEl());
|
|
1137
1139
|
refreshIcons();
|
|
1138
1140
|
reconcileSessionContextMenu();
|
|
1139
1141
|
reconcileFolderMenu();
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from './sidebar-mates.js';
|
|
15
15
|
import { initSidebarMobile } from './sidebar-mobile.js';
|
|
16
16
|
import { store } from './store.js';
|
|
17
|
+
import { restoreSidebarCollapseFocus } from './sidebar-collapse-focus.js';
|
|
17
18
|
|
|
18
19
|
var ctx;
|
|
19
20
|
var _syncResizeHandles = null;
|
|
@@ -66,9 +67,11 @@ export function toggleSidebarCollapse() {
|
|
|
66
67
|
var layout = document.getElementById("layout");
|
|
67
68
|
if (!layout && ctx) layout = ctx.$("layout");
|
|
68
69
|
if (!layout) return;
|
|
70
|
+
var previousFocus = document.activeElement;
|
|
69
71
|
var collapsed = layout.classList.toggle("sidebar-collapsed");
|
|
70
72
|
try { localStorage.setItem("sidebar-collapsed", collapsed ? "1" : ""); } catch (e) {}
|
|
71
73
|
updateSidebarToggleState(collapsed);
|
|
74
|
+
restoreSidebarCollapseFocus(collapsed, previousFocus);
|
|
72
75
|
if (ctx) setTimeout(function () { syncResizeHandles(); }, 210);
|
|
73
76
|
}
|
|
74
77
|
|
|
@@ -78,10 +81,10 @@ function updateSidebarToggleState(collapsed) {
|
|
|
78
81
|
buttons[i].setAttribute("aria-expanded", collapsed ? "false" : "true");
|
|
79
82
|
buttons[i].title = collapsed ? "Open sidebar" : "Collapse sidebar";
|
|
80
83
|
buttons[i].setAttribute("aria-label", collapsed ? "Open sidebar" : "Collapse sidebar");
|
|
84
|
+
buttons[i].setAttribute("aria-controls", "sidebar-column mate-sidebar-column");
|
|
81
85
|
if (buttons[i].id === "sidebar-shell-expand-btn") {
|
|
82
|
-
var splitVisible = document.getElementById("split-host");
|
|
83
86
|
var desktop = !window.matchMedia || window.matchMedia("(min-width: 769px)").matches;
|
|
84
|
-
buttons[i].hidden = !collapsed || !desktop
|
|
87
|
+
buttons[i].hidden = !collapsed || !desktop;
|
|
85
88
|
}
|
|
86
89
|
}
|
|
87
90
|
}
|
|
@@ -275,7 +278,7 @@ export function initSidebar(_ctx) {
|
|
|
275
278
|
if (!resizeHandle || !sidebarColumn) return;
|
|
276
279
|
var rect = sidebarColumn.getBoundingClientRect();
|
|
277
280
|
var parentRect = sidebarColumn.parentElement.getBoundingClientRect();
|
|
278
|
-
resizeHandle.style.left = (rect.right - parentRect.left) + "px";
|
|
281
|
+
resizeHandle.style.left = (rect.right - parentRect.left - sidebarColumn.parentElement.clientLeft) + "px";
|
|
279
282
|
}
|
|
280
283
|
|
|
281
284
|
if (resizeHandle && sidebarColumn) {
|
|
@@ -285,9 +288,7 @@ export function initSidebar(_ctx) {
|
|
|
285
288
|
if (!dragging) return;
|
|
286
289
|
e.preventDefault();
|
|
287
290
|
var clientX = e.touches ? e.touches[0].clientX : e.clientX;
|
|
288
|
-
var
|
|
289
|
-
var stripWidth = iconStrip ? iconStrip.offsetWidth : 72;
|
|
290
|
-
var newWidth = clientX - stripWidth;
|
|
291
|
+
var newWidth = clientX - sidebarColumn.getBoundingClientRect().left;
|
|
291
292
|
if (newWidth < 192) newWidth = 192;
|
|
292
293
|
if (newWidth > 320) newWidth = 320;
|
|
293
294
|
sidebarColumn.style.width = newWidth + "px";
|
|
@@ -360,7 +361,7 @@ export function initSidebar(_ctx) {
|
|
|
360
361
|
if (!mateResizeHandle || !mateSidebarCol) return;
|
|
361
362
|
var rect = mateSidebarCol.getBoundingClientRect();
|
|
362
363
|
var parentRect = mateSidebarCol.parentElement.getBoundingClientRect();
|
|
363
|
-
mateResizeHandle.style.left = (rect.right - parentRect.left) + "px";
|
|
364
|
+
mateResizeHandle.style.left = (rect.right - parentRect.left - mateSidebarCol.parentElement.clientLeft) + "px";
|
|
364
365
|
}
|
|
365
366
|
|
|
366
367
|
if (mateResizeHandle && mateSidebarCol) {
|
|
@@ -370,9 +371,7 @@ export function initSidebar(_ctx) {
|
|
|
370
371
|
if (!mateDragging) return;
|
|
371
372
|
e.preventDefault();
|
|
372
373
|
var clientX = e.touches ? e.touches[0].clientX : e.clientX;
|
|
373
|
-
var
|
|
374
|
-
var stripWidth = iconStrip ? iconStrip.offsetWidth : 72;
|
|
375
|
-
var newWidth = clientX - stripWidth;
|
|
374
|
+
var newWidth = clientX - mateSidebarCol.getBoundingClientRect().left;
|
|
376
375
|
if (newWidth < 192) newWidth = 192;
|
|
377
376
|
if (newWidth > 320) newWidth = 320;
|
|
378
377
|
mateSidebarCol.style.width = newWidth + "px";
|