mirror of
https://github.com/mjl-/mox.git
synced 2025-07-10 09:54:40 +03:00
webmail: move 2 config options from localstorage to the settings popup, storing their values on the server
these settings are applied anywhere the webmail is open. the settings are for showing keyboard shortcuts in the lower right after a mouse interaction, and showing additional headers. the shorcuts were configurable in the "help" popup before. the additional headers were only configurable through the developer console before. the "mailto:" (un)register buttons are now in the settings popup too.
This commit is contained in:
@ -50,10 +50,6 @@ To simulate slow API calls and SSE events:
|
||||
|
||||
localStorage.setItem('sherpats-debug', JSON.stringify({waitMinMsec: 2000, waitMaxMsec: 4000}))
|
||||
|
||||
Show additional headers of messages:
|
||||
|
||||
settingsPut({...settings, showHeaders: ['Delivered-To', 'User-Agent', 'X-Mailer', 'Message-Id', 'List-Id', 'List-Post', 'X-Mox-Reason', 'TLS-Required']})
|
||||
|
||||
Enable logging and reload afterwards:
|
||||
|
||||
localStorage.setItem('log', 'yes')
|
||||
@ -147,7 +143,6 @@ try {
|
||||
let accountSettings: api.Settings
|
||||
|
||||
const defaultSettings = {
|
||||
showShortcuts: true, // Whether to briefly show shortcuts in bottom left when a button is clicked that has a keyboard shortcut.
|
||||
mailboxesWidth: 240,
|
||||
layout: 'auto', // Automatic switching between left/right and top/bottom layout, based on screen width.
|
||||
leftWidthPct: 50, // Split in percentage of remaining width for left/right layout.
|
||||
@ -160,7 +155,6 @@ const defaultSettings = {
|
||||
ignoreErrorsUntil: 0, // For unhandled javascript errors/rejected promises, we normally show a popup for details, but users can ignore them for a week at a time.
|
||||
mailboxCollapsed: {} as {[mailboxID: number]: boolean}, // Mailboxes that are collapsed.
|
||||
showAllHeaders: false, // Whether to show all message headers.
|
||||
showHeaders: [] as string[], // Additional message headers to show.
|
||||
threading: api.ThreadMode.ThreadOn,
|
||||
checkConsistency: location.hostname === 'localhost', // Enable UI update consistency checks, default only for local development.
|
||||
composeWidth: 0,
|
||||
@ -195,13 +189,6 @@ const parseSettings = (): typeof defaultSettings => {
|
||||
if (!mailboxCollapsed || typeof mailboxCollapsed !== 'object') {
|
||||
mailboxCollapsed = def.mailboxCollapsed
|
||||
}
|
||||
const getStringArray = (k: string): string[] => {
|
||||
const v = x[k]
|
||||
if (v && Array.isArray(v) && (v.length === 0 || typeof v[0] === 'string')) {
|
||||
return v
|
||||
}
|
||||
return def[k] as string[]
|
||||
}
|
||||
|
||||
return {
|
||||
refine: getString('refine'),
|
||||
@ -214,10 +201,8 @@ const parseSettings = (): typeof defaultSettings => {
|
||||
msglistfromPct: getInt('msglistfromPct'),
|
||||
ignoreErrorsUntil: getInt('ignoreErrorsUntil'),
|
||||
layout: getString('layout', 'auto', 'leftright', 'topbottom'),
|
||||
showShortcuts: getBool('showShortcuts'),
|
||||
mailboxCollapsed: mailboxCollapsed,
|
||||
showAllHeaders: getBool('showAllHeaders'),
|
||||
showHeaders: getStringArray('showHeaders'),
|
||||
threading: getString('threading', api.ThreadMode.ThreadOff, api.ThreadMode.ThreadOn, api.ThreadMode.ThreadUnread) as api.ThreadMode,
|
||||
checkConsistency: getBool('checkConsistency'),
|
||||
composeWidth: getInt('composeWidth'),
|
||||
@ -387,7 +372,7 @@ const envelopeIdentity = (l: api.MessageAddress[]): api.MessageAddress | null =>
|
||||
let shortcutElem = dom.div(css('shortcutFlash', {fontSize: '2em', position: 'absolute', left: '.25em', bottom: '.25em', backgroundColor: '#888', padding: '0.25em .5em', color: 'white', borderRadius: '.15em'}))
|
||||
let shortcutTimer = 0
|
||||
const showShortcut = (c: string) => {
|
||||
if (!settings.showShortcuts) {
|
||||
if (accountSettings?.NoShowShortcuts) {
|
||||
return
|
||||
}
|
||||
if (shortcutTimer) {
|
||||
@ -1119,6 +1104,8 @@ const cmdSettings = async () => {
|
||||
let quoting: HTMLSelectElement
|
||||
let showAddressSecurity: HTMLInputElement
|
||||
let showHTML: HTMLInputElement
|
||||
let showShortcuts: HTMLInputElement
|
||||
let showHeaders: HTMLTextAreaElement
|
||||
|
||||
if (!accountSettings) {
|
||||
throw new Error('No account settings fetched yet.')
|
||||
@ -1137,6 +1124,8 @@ const cmdSettings = async () => {
|
||||
Quoting: quoting.value as api.Quoting,
|
||||
ShowAddressSecurity: showAddressSecurity.checked,
|
||||
ShowHTML: showHTML.checked,
|
||||
NoShowShortcuts: !showShortcuts.checked,
|
||||
ShowHeaders: showHeaders.value.split('\n').map(s => s.trim()).filter(s => !!s),
|
||||
}
|
||||
await withDisabled(fieldset, client.SettingsSave(accSet))
|
||||
accountSettings = accSet
|
||||
@ -1171,8 +1160,61 @@ const cmdSettings = async () => {
|
||||
dom.label(
|
||||
style({margin: '1ex 0', display: 'block'}),
|
||||
showHTML=dom.input(attr.type('checkbox'), accountSettings.ShowHTML ? attr.checked('') : []),
|
||||
' Show HTML instead of text version by default',
|
||||
' Show email as HTML instead of text by default for first-time senders',
|
||||
attr.title('Whether to show HTML or text is remembered per sender. This sets the default for unknown correspondents.'),
|
||||
),
|
||||
|
||||
dom.label(
|
||||
style({margin: '1ex 0', display: 'block'}),
|
||||
showShortcuts=dom.input(attr.type('checkbox'), accountSettings.NoShowShortcuts ? [] : attr.checked('')),
|
||||
' Show shortcut keys in bottom left after interaction with mouse',
|
||||
),
|
||||
|
||||
dom.label(
|
||||
style({margin: '1ex 0', display: 'block'}),
|
||||
dom.div('Show additional headers'),
|
||||
showHeaders=dom.textarea(
|
||||
new String((accountSettings.ShowHeaders || []).join('\n')),
|
||||
style({width: '100%'}),
|
||||
attr.rows(''+Math.max(3, 1+(accountSettings.ShowHeaders || []).length)),
|
||||
),
|
||||
dom.div(style({fontStyle: 'italic'}), 'One header name per line, for example Delivered-To, X-Mox-Reason, User-Agent, ...'),
|
||||
),
|
||||
|
||||
|
||||
dom.div(
|
||||
style({marginTop: '2ex'}),
|
||||
'Register "mailto:" links with the browser/operating system to compose a message in webmail.',
|
||||
dom.br(),
|
||||
dom.clickbutton('Register', attr.title('In most browsers, registering is only allowed on HTTPS URLs. Your browser may ask for confirmation. If nothing appears to happen, the registration may already have been present.'), function click() {
|
||||
if (!window.navigator.registerProtocolHandler) {
|
||||
window.alert('Registering a protocol handler ("mailto:") is not supported by your browser.')
|
||||
return
|
||||
}
|
||||
try {
|
||||
window.navigator.registerProtocolHandler('mailto', '#compose %s')
|
||||
window.alert('"mailto:"-links have been registered')
|
||||
} catch (err) {
|
||||
window.alert('Error registering "mailto:" protocol handler: '+errmsg(err))
|
||||
}
|
||||
}),
|
||||
' ',
|
||||
dom.clickbutton('Unregister', attr.title('Not all browsers implement unregistering via JavaScript.'), function click() {
|
||||
// Not supported on firefox at the time of writing, and the signature is not in the types.
|
||||
if (!(window.navigator as any).unregisterProtocolHandler) {
|
||||
window.alert('Unregistering a protocol handler ("mailto:") via JavaScript is not supported by your browser. See your browser settings to unregister.')
|
||||
return
|
||||
}
|
||||
try {
|
||||
(window.navigator as any).unregisterProtocolHandler('mailto', '#compose %s')
|
||||
} catch (err) {
|
||||
window.alert('Error unregistering "mailto:" protocol handler: '+errmsg(err))
|
||||
return
|
||||
}
|
||||
window.alert('"mailto:" protocol handler unregistered.')
|
||||
}),
|
||||
),
|
||||
|
||||
dom.br(),
|
||||
dom.div(
|
||||
dom.submitbutton('Save'),
|
||||
@ -1184,7 +1226,7 @@ const cmdSettings = async () => {
|
||||
|
||||
// Show help popup, with shortcuts and basic explanation.
|
||||
const cmdHelp = async () => {
|
||||
const remove = popup(
|
||||
popup(
|
||||
css('popupHelp', {padding: '1em 1em 2em 1em'}),
|
||||
dom.h1('Help and keyboard shortcuts'),
|
||||
dom.div(style({display: 'flex'}),
|
||||
@ -1299,51 +1341,6 @@ const cmdHelp = async () => {
|
||||
dom.div(style({marginBottom: '1ex'}), 'Multiple messages can be selected by clicking messages while holding the control and/or shift keys. Dragging messages and dropping them on a mailbox moves the messages to that mailbox.'),
|
||||
dom.div(style({marginBottom: '1ex'}), 'Text that changes ', dom.span(attr.title('Unicode blocks, e.g. from basic latin to cyrillic, or to emoticons.'), '"character groups"'), ' without whitespace has an ', dom.span(dom._class('scriptswitch'), 'orange underline'), ', which can be a sign of an intent to mislead (e.g. phishing).'),
|
||||
|
||||
settings.showShortcuts ?
|
||||
dom.div(style({marginTop: '2ex'}), 'Shortcut keys for mouse operation are shown in the bottom left. ',
|
||||
dom.clickbutton('Disable', function click() {
|
||||
settingsPut({...settings, showShortcuts: false})
|
||||
remove()
|
||||
cmdHelp()
|
||||
})
|
||||
) :
|
||||
dom.div(style({marginTop: '2ex'}), 'Shortcut keys for mouse operation are currently not shown. ',
|
||||
dom.clickbutton('Enable', function click() {
|
||||
settingsPut({...settings, showShortcuts: true})
|
||||
remove()
|
||||
cmdHelp()
|
||||
})
|
||||
),
|
||||
dom.div(
|
||||
style({marginTop: '2ex'}),
|
||||
'To start composing a message when opening a "mailto:" link, register this application with your browser/system. ',
|
||||
dom.clickbutton('Register', attr.title('In most browsers, registering is only allowed on HTTPS URLs. Your browser may ask for confirmation. If nothing appears to happen, the registration may already have been present.'), function click() {
|
||||
if (!window.navigator.registerProtocolHandler) {
|
||||
window.alert('Registering a protocol handler ("mailto:") is not supported by your browser.')
|
||||
return
|
||||
}
|
||||
try {
|
||||
window.navigator.registerProtocolHandler('mailto', '#compose %s')
|
||||
} catch (err) {
|
||||
window.alert('Error registering "mailto:" protocol handler: '+errmsg(err))
|
||||
}
|
||||
}),
|
||||
' ',
|
||||
dom.clickbutton('Unregister', attr.title('Not all browsers implement unregistering via JavaScript.'), function click() {
|
||||
// Not supported on firefox at the time of writing, and the signature is not in the types.
|
||||
if (!(window.navigator as any).unregisterProtocolHandler) {
|
||||
window.alert('Unregistering a protocol handler ("mailto:") via JavaScript is not supported by your browser. See your browser settings to unregister.')
|
||||
return
|
||||
}
|
||||
try {
|
||||
(window.navigator as any).unregisterProtocolHandler('mailto', '#compose %s')
|
||||
} catch (err) {
|
||||
window.alert('Error unregistering "mailto:" protocol handler: '+errmsg(err))
|
||||
return
|
||||
}
|
||||
window.alert('"mailto:" protocol handler unregistered.')
|
||||
}),
|
||||
),
|
||||
dom.div(style({marginTop: '2ex'}), 'Mox is open source email server software, this is version ', moxversion, ', see ', dom.a(attr.href('licenses.txt'), 'licenses'), '.', dom.br(), 'Feedback, including bug reports, is appreciated! ', link('https://github.com/mjl-/mox/issues/new')),
|
||||
),
|
||||
),
|
||||
@ -3256,7 +3253,7 @@ const newMsgView = (miv: MsgitemView, msglistView: MsglistView, listMailboxes: l
|
||||
}
|
||||
loadButtons(parsedMessageOpt || null)
|
||||
|
||||
loadMsgheaderView(msgheaderElem, miv.messageitem, settings.showHeaders, refineKeyword, false)
|
||||
loadMsgheaderView(msgheaderElem, miv.messageitem, accountSettings.ShowHeaders || [], refineKeyword, false)
|
||||
|
||||
const headerTextMildStyle = css('headerTextMild', {textAlign: 'right', color: styles.colorMild})
|
||||
|
||||
@ -3515,13 +3512,14 @@ const newMsgView = (miv: MsgitemView, msglistView: MsglistView, listMailboxes: l
|
||||
}
|
||||
|
||||
const loadMoreHeaders = (pm: api.ParsedMessage) => {
|
||||
if (settings.showHeaders.length === 0) {
|
||||
const hl = accountSettings.ShowHeaders || []
|
||||
if (hl.length === 0) {
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < settings.showHeaders.length; i++) {
|
||||
for (let i = 0; i < hl.length; i++) {
|
||||
msgheaderElem.children[msgheaderElem.children.length-1].remove()
|
||||
}
|
||||
settings.showHeaders.forEach(k => {
|
||||
hl.forEach(k => {
|
||||
const vl = pm.Headers?.[k]
|
||||
if (!vl || vl.length === 0) {
|
||||
return
|
||||
@ -3544,7 +3542,7 @@ const newMsgView = (miv: MsgitemView, msglistView: MsglistView, listMailboxes: l
|
||||
updateKeywords: async (modseq: number, keywords: string[]) => {
|
||||
mi.Message.ModSeq = modseq
|
||||
mi.Message.Keywords = keywords
|
||||
loadMsgheaderView(msgheaderElem, miv.messageitem, settings.showHeaders, refineKeyword, false)
|
||||
loadMsgheaderView(msgheaderElem, miv.messageitem, accountSettings.ShowHeaders || [], refineKeyword, false)
|
||||
loadMoreHeaders(await parsedMessagePromise)
|
||||
},
|
||||
}
|
||||
|
Reference in New Issue
Block a user