559 lines
15 KiB
JavaScript
559 lines
15 KiB
JavaScript
/* extension.js
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
/*
|
|
Swaths of pref related code borrowed from Clipboard Indicator, an amazing extension
|
|
https://github.com/Tudmotu/gnome-shell-extension-clipboard-indicator
|
|
https://extensions.gnome.org/extension/779/clipboard-indicator/
|
|
*/
|
|
import Gio from 'gi://Gio'
|
|
import Gtk from 'gi://Gtk?version=4.0'
|
|
import Adw from 'gi://Adw'
|
|
|
|
import {
|
|
ExtensionPreferences,
|
|
gettext as _,
|
|
} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'
|
|
|
|
import * as prefFields from './utils/prefFields.js'
|
|
import {
|
|
getCurrentCalendar,
|
|
getCurrentTimezone,
|
|
getCurrentLocale,
|
|
updateLevelToString,
|
|
TEXT_ALIGN_START,
|
|
TEXT_ALIGN_CENTER,
|
|
TEXT_ALIGN_END,
|
|
} from './utils/general.js'
|
|
import { useAddRow, createLabel, addBox, table, a, b } from './utils/markup.js'
|
|
import { CALENDAR_LIST, FormatterManager } from './utils/formatter.js'
|
|
|
|
class Preferences {
|
|
constructor(settings) {
|
|
this.settings = settings
|
|
this.formatters = new FormatterManager()
|
|
this._previewErrorCount = 0
|
|
this.box = {}
|
|
this.initUI()
|
|
this.formatters
|
|
.loadFormatters()
|
|
.then(() => {
|
|
this.createUI()
|
|
this.UIShowHideFormatterAbility(
|
|
this.formatters.getFormatter(this._formatter.active_id).can
|
|
)
|
|
this.generatePreview()
|
|
})
|
|
.catch((e) => {
|
|
console.error('Date Menu Formatter error:', e)
|
|
})
|
|
}
|
|
|
|
initUI() {
|
|
this.main = new Gtk.Grid({
|
|
margin_top: 10,
|
|
margin_bottom: 10,
|
|
margin_start: 10,
|
|
margin_end: 10,
|
|
row_spacing: 12,
|
|
column_spacing: 18,
|
|
column_homogeneous: false,
|
|
row_homogeneous: false,
|
|
})
|
|
this.addRow = useAddRow(this.main)
|
|
this.addSeparator = () => this.addRow(null, new Gtk.Separator())
|
|
}
|
|
|
|
createUI() {
|
|
this.UIcreateFormatterSetting()
|
|
this.UIcreateFontSizeSetting()
|
|
this.UIcreateTextAlignSetting()
|
|
this.UIcreatePatternSetting()
|
|
this.UIcreatePatternPreview()
|
|
this.addSeparator()
|
|
this.UIcreateUpdateLevelSetting()
|
|
this.UIcreateDefaultLocaleSetting()
|
|
this.UIcreateDefaultCalendarSetting()
|
|
this.UIcreateDefaultTimezoneSetting()
|
|
this.addSeparator()
|
|
this.UIcreateRemoveUnreadMessagesSetting()
|
|
this.UIcreateAllPanelsSetting()
|
|
this.addSeparator()
|
|
this.UIcreateFormatterHelp()
|
|
}
|
|
|
|
UIcreateFormatterSetting() {
|
|
const formatterSelect = new Gtk.ComboBoxText({
|
|
hexpand: true,
|
|
halign: Gtk.Align.FILL,
|
|
})
|
|
|
|
this.formatters.asList().forEach(({ key, name }) => {
|
|
formatterSelect.append(key, name)
|
|
})
|
|
|
|
formatterSelect.set_active_id(
|
|
this.settings.get_string(prefFields.FORMATTER)
|
|
)
|
|
this._formatter = formatterSelect
|
|
this.addRow(createLabel(_('Formatter')), formatterSelect)
|
|
|
|
this.settings.bind(
|
|
prefFields.FORMATTER,
|
|
formatterSelect,
|
|
'active-id',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
formatterSelect.connect('changed', () => {
|
|
this.setHelpMarkup(
|
|
this.formatters.getFormatterHelp(this._formatter.active_id)
|
|
)
|
|
this.UIShowHideFormatterAbility(
|
|
this.formatters.getFormatter(this._formatter.active_id).can
|
|
)
|
|
this.generatePreview()
|
|
})
|
|
}
|
|
|
|
UIShowHideFormatterAbility(can) {
|
|
this.box.locale(can.customLocale)
|
|
this.box.calendar(can.customCalendar)
|
|
this.box.timezone(can.customTimezone)
|
|
}
|
|
|
|
UIcreatePatternSetting() {
|
|
const patternEdit = new Gtk.Entry({ buffer: new Gtk.EntryBuffer() })
|
|
|
|
this.addRow(createLabel(_('Pattern')), patternEdit)
|
|
this._pattern = patternEdit.buffer
|
|
|
|
this.settings.bind(
|
|
prefFields.PATTERN,
|
|
patternEdit.buffer,
|
|
'text',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
patternEdit.buffer.connect_after(
|
|
'inserted-text',
|
|
this.generatePreview.bind(this)
|
|
)
|
|
patternEdit.buffer.connect_after(
|
|
'deleted-text',
|
|
this.generatePreview.bind(this)
|
|
)
|
|
}
|
|
|
|
UIcreatePatternPreview() {
|
|
this._preview = createLabel('')
|
|
this._preview.set_use_markup(true)
|
|
this.addRow(createLabel(_('Preview')), this._preview)
|
|
}
|
|
|
|
UIcreateUpdateLevelSetting() {
|
|
const updateLevelSelect = new Gtk.ComboBoxText({
|
|
hexpand: true,
|
|
halign: Gtk.Align.FILL,
|
|
})
|
|
|
|
for (let i = 0; i <= 15; i++) {
|
|
updateLevelSelect.append('' + i, updateLevelToString(i))
|
|
}
|
|
updateLevelSelect.set_active_id(
|
|
'' + this.settings.get_int(prefFields.UPDATE_LEVEL)
|
|
)
|
|
this.addRow(createLabel(_('Update')), updateLevelSelect)
|
|
|
|
updateLevelSelect.connect('changed', () => {
|
|
this.settings.set_int(
|
|
prefFields.UPDATE_LEVEL,
|
|
parseInt(updateLevelSelect.active_id)
|
|
)
|
|
})
|
|
}
|
|
|
|
UIcreateDefaultLocaleSetting() {
|
|
const useDefaultLocaleLabel = createLabel(
|
|
_('Use default locale') + ` (${getCurrentLocale()})`
|
|
)
|
|
const localeBox = new Gtk.Box({
|
|
orientation: Gtk.Orientation.HORIZONTAL,
|
|
spacing: 30,
|
|
})
|
|
const useDefaultLocaleEdit = new Gtk.Switch({
|
|
vexpand: false,
|
|
valign: Gtk.Align.CENTER,
|
|
})
|
|
const customLocaleEdit = new Gtk.Entry({ buffer: new Gtk.EntryBuffer() })
|
|
addBox(localeBox, useDefaultLocaleEdit)
|
|
addBox(localeBox, customLocaleEdit)
|
|
|
|
this.addRow(useDefaultLocaleLabel, localeBox)
|
|
|
|
this.box.locale = (show) => {
|
|
if (show) {
|
|
localeBox.show()
|
|
useDefaultLocaleLabel.show()
|
|
} else {
|
|
localeBox.hide()
|
|
useDefaultLocaleLabel.hide()
|
|
}
|
|
}
|
|
this._customLocale = customLocaleEdit.buffer
|
|
this._useDefaultLocale = useDefaultLocaleEdit
|
|
|
|
this.settings.bind(
|
|
prefFields.USE_DEFAULT_LOCALE,
|
|
useDefaultLocaleEdit,
|
|
'active',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
|
|
this.settings.bind(
|
|
prefFields.USE_DEFAULT_LOCALE,
|
|
customLocaleEdit,
|
|
'sensitive',
|
|
Gio.SettingsBindFlags.GET |
|
|
Gio.SettingsBindFlags.NO_SENSITIVITY |
|
|
Gio.SettingsBindFlags.INVERT_BOOLEAN
|
|
)
|
|
|
|
this.settings.bind(
|
|
prefFields.CUSTOM_LOCALE,
|
|
customLocaleEdit.buffer,
|
|
'text',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
|
|
useDefaultLocaleEdit.connect('state-set', this.generatePreview.bind(this))
|
|
customLocaleEdit.buffer.connect_after(
|
|
'inserted-text',
|
|
this.generatePreview.bind(this)
|
|
)
|
|
customLocaleEdit.buffer.connect_after(
|
|
'deleted-text',
|
|
this.generatePreview.bind(this)
|
|
)
|
|
}
|
|
UIcreateDefaultCalendarSetting() {
|
|
const defaultCalendarName = CALENDAR_LIST.find(
|
|
({ key }) => key === getCurrentCalendar()
|
|
).name
|
|
|
|
const useDefaultCalendarLabel = createLabel(
|
|
_('Use default calendar') + ` (${defaultCalendarName})`
|
|
)
|
|
const calendarBox = new Gtk.Box({
|
|
orientation: Gtk.Orientation.HORIZONTAL,
|
|
spacing: 30,
|
|
})
|
|
const useDefaultCalendarEdit = new Gtk.Switch({
|
|
vexpand: false,
|
|
valign: Gtk.Align.CENTER,
|
|
})
|
|
const customCalendarSelect = new Gtk.ComboBoxText({
|
|
hexpand: false,
|
|
halign: Gtk.Align.FILL,
|
|
})
|
|
|
|
CALENDAR_LIST.forEach(({ key, name, description }) => {
|
|
customCalendarSelect.append(key, `${name} -> "${description}"`)
|
|
})
|
|
|
|
customCalendarSelect.set_active_id(
|
|
this.settings.get_string(prefFields.CUSTOM_CALENDAR) ||
|
|
getCurrentCalendar()
|
|
)
|
|
|
|
addBox(calendarBox, useDefaultCalendarEdit)
|
|
addBox(calendarBox, customCalendarSelect)
|
|
|
|
this.addRow(useDefaultCalendarLabel, calendarBox)
|
|
|
|
this.box.calendar = (show) => {
|
|
if (show) {
|
|
calendarBox.show()
|
|
useDefaultCalendarLabel.show()
|
|
} else {
|
|
calendarBox.hide()
|
|
useDefaultCalendarLabel.hide()
|
|
}
|
|
}
|
|
this._customCalendar = customCalendarSelect
|
|
this._useDefaultCalendar = useDefaultCalendarEdit
|
|
|
|
this.settings.bind(
|
|
prefFields.USE_DEFAULT_CALENDAR,
|
|
useDefaultCalendarEdit,
|
|
'active',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
this.settings.bind(
|
|
prefFields.CUSTOM_CALENDAR,
|
|
customCalendarSelect,
|
|
'active-id',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
this.settings.bind(
|
|
prefFields.USE_DEFAULT_CALENDAR,
|
|
customCalendarSelect,
|
|
'sensitive',
|
|
Gio.SettingsBindFlags.GET |
|
|
Gio.SettingsBindFlags.NO_SENSITIVITY |
|
|
Gio.SettingsBindFlags.INVERT_BOOLEAN
|
|
)
|
|
useDefaultCalendarEdit.connect('state-set', this.generatePreview.bind(this))
|
|
customCalendarSelect.connect('changed', this.generatePreview.bind(this))
|
|
}
|
|
|
|
UIcreateDefaultTimezoneSetting() {
|
|
const useDefaultTimezoneLabel = createLabel(
|
|
_('Use default timezone') + ` (${getCurrentTimezone()})`
|
|
)
|
|
const timezoneBox = new Gtk.Box({
|
|
orientation: Gtk.Orientation.HORIZONTAL,
|
|
spacing: 30,
|
|
})
|
|
const useDefaultTimezoneEdit = new Gtk.Switch({
|
|
vexpand: false,
|
|
valign: Gtk.Align.CENTER,
|
|
})
|
|
|
|
const customTimezoneEdit = new Gtk.Entry({ buffer: new Gtk.EntryBuffer() })
|
|
|
|
addBox(timezoneBox, useDefaultTimezoneEdit)
|
|
addBox(timezoneBox, customTimezoneEdit)
|
|
|
|
this.addRow(useDefaultTimezoneLabel, timezoneBox)
|
|
|
|
this.box.timezone = (show) => {
|
|
if (show) {
|
|
timezoneBox.show()
|
|
useDefaultTimezoneLabel.show()
|
|
} else {
|
|
timezoneBox.hide()
|
|
useDefaultTimezoneLabel.hide()
|
|
}
|
|
}
|
|
this._customTimezone = customTimezoneEdit.buffer
|
|
this._useDefaultTimezone = useDefaultTimezoneEdit
|
|
|
|
this.settings.bind(
|
|
prefFields.USE_DEFAULT_TIMEZONE,
|
|
useDefaultTimezoneEdit,
|
|
'active',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
this.settings.bind(
|
|
prefFields.CUSTOM_TIMEZONE,
|
|
customTimezoneEdit.buffer,
|
|
'text',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
this.settings.bind(
|
|
prefFields.USE_DEFAULT_TIMEZONE,
|
|
customTimezoneEdit,
|
|
'sensitive',
|
|
Gio.SettingsBindFlags.GET |
|
|
Gio.SettingsBindFlags.NO_SENSITIVITY |
|
|
Gio.SettingsBindFlags.INVERT_BOOLEAN
|
|
)
|
|
|
|
useDefaultTimezoneEdit.connect('state-set', this.generatePreview.bind(this))
|
|
|
|
customTimezoneEdit.buffer.connect_after(
|
|
'inserted-text',
|
|
this.generatePreview.bind(this)
|
|
)
|
|
customTimezoneEdit.buffer.connect_after(
|
|
'deleted-text',
|
|
this.generatePreview.bind(this)
|
|
)
|
|
}
|
|
|
|
UIcreateRemoveUnreadMessagesSetting() {
|
|
const removeMessagesIndicatorEdit = new Gtk.Switch()
|
|
this.addRow(
|
|
createLabel(_('Remove unread messages indicator')),
|
|
removeMessagesIndicatorEdit
|
|
)
|
|
|
|
this.settings.bind(
|
|
prefFields.REMOVE_MESSAGES_INDICATOR,
|
|
removeMessagesIndicatorEdit,
|
|
'active',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
}
|
|
|
|
UIcreateAllPanelsSetting() {
|
|
const applyAllPanelsEdit = new Gtk.Switch()
|
|
|
|
this.addRow(
|
|
createLabel(_('Apply to all panels (Dash to Panel)')),
|
|
applyAllPanelsEdit
|
|
)
|
|
this.settings.bind(
|
|
prefFields.APPLY_ALL_PANELS,
|
|
applyAllPanelsEdit,
|
|
'active',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
}
|
|
|
|
UIcreateFontSizeSetting() {
|
|
const fontSizeEdit = new Gtk.SpinButton({
|
|
adjustment: new Gtk.Adjustment({
|
|
lower: 4,
|
|
upper: 30,
|
|
step_increment: 1,
|
|
}),
|
|
})
|
|
|
|
this.addRow(createLabel(_('Font size')), fontSizeEdit)
|
|
|
|
fontSizeEdit.connect(
|
|
'output',
|
|
function (spin) {
|
|
spin.text = `${spin.value} pt`
|
|
this.FONT_SIZE = spin.value
|
|
return true
|
|
}.bind(this)
|
|
)
|
|
this.settings.bind(
|
|
prefFields.FONT_SIZE,
|
|
fontSizeEdit,
|
|
'value',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
)
|
|
}
|
|
UIcreateTextAlignSetting() {
|
|
const tAlignBox = new Gtk.Box({
|
|
orientation: Gtk.Orientation.HORIZONTAL,
|
|
spacing: 0,
|
|
})
|
|
tAlignBox.set_css_classes(['linked'])
|
|
|
|
const buttons = [
|
|
{
|
|
btn: Gtk.Button.new_from_icon_name('format-justify-left-symbolic'),
|
|
key: TEXT_ALIGN_START,
|
|
},
|
|
{
|
|
btn: Gtk.Button.new_from_icon_name('format-justify-center-symbolic'),
|
|
key: TEXT_ALIGN_CENTER,
|
|
},
|
|
{
|
|
btn: Gtk.Button.new_from_icon_name('format-justify-right-symbolic'),
|
|
key: TEXT_ALIGN_END,
|
|
},
|
|
]
|
|
const settings = this.settings
|
|
const selected = {
|
|
get value() {
|
|
return settings.get_string(prefFields.TEXT_ALIGN)
|
|
},
|
|
set value(sel) {
|
|
buttons.forEach(({ btn, key }) => {
|
|
btn.set_sensitive(key !== sel)
|
|
})
|
|
settings.set_string(prefFields.TEXT_ALIGN, sel)
|
|
},
|
|
}
|
|
selected.value = selected.value || TEXT_ALIGN_CENTER
|
|
buttons.forEach(({ btn, key }) => {
|
|
addBox(tAlignBox, btn)
|
|
btn.connect('clicked', function () {
|
|
selected.value = key
|
|
})
|
|
})
|
|
|
|
this.addRow(createLabel(_('Align Text')), tAlignBox)
|
|
}
|
|
|
|
UIcreateFormatterHelp() {
|
|
const left = createLabel('')
|
|
const right = createLabel('')
|
|
|
|
this.setHelpMarkup = (help) => {
|
|
left.set_markup(`${b('Available pattern components')}${table(help.left)}`)
|
|
right.set_markup(`${a(help.link, 'Full list (web)')}${table(help.right)}`)
|
|
}
|
|
|
|
this.setHelpMarkup(
|
|
this.formatters.getFormatterHelp(this._formatter.active_id)
|
|
)
|
|
|
|
this.addRow(left, right)
|
|
}
|
|
|
|
generatePreview() {
|
|
const locale = this._useDefaultLocale.active
|
|
? getCurrentLocale()
|
|
: this._customLocale.text
|
|
const calendar = this._useDefaultCalendar.active
|
|
? getCurrentCalendar()
|
|
: this._customCalendar.active_id
|
|
const timezone = this._useDefaultTimezone.active
|
|
? getCurrentTimezone()
|
|
: this._customTimezone.text
|
|
|
|
if (this._pattern.text.length > 1) {
|
|
try {
|
|
const formatter = this.formatters.getFormatter(
|
|
this._formatter.active_id
|
|
)
|
|
this._preview.label = new formatter(timezone, locale, calendar).format(
|
|
this._pattern.text,
|
|
new Date()
|
|
)
|
|
this._previewErrorCount = 0
|
|
} catch (e) {
|
|
this._previewErrorCount++
|
|
if (this._previewErrorCount > 2) {
|
|
this._preview.label = 'ERROR: ' + e.message
|
|
}
|
|
}
|
|
} else {
|
|
this._preview.label = ''
|
|
this._previewErrorCount = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
export default class DateMenuFormatterPreferences extends ExtensionPreferences {
|
|
getPreferencesWidget() {
|
|
const frame = new Gtk.Box()
|
|
const widget = new Preferences(this.getSettings())
|
|
addBox(frame, widget.main)
|
|
if (frame.show_all) frame.show_all()
|
|
return frame
|
|
}
|
|
fillPreferencesWindow(window) {
|
|
window._settings = this.getSettings()
|
|
window.set_size_request(1000, 700)
|
|
const page = new Adw.PreferencesPage()
|
|
|
|
const group = new Adw.PreferencesGroup({
|
|
title: _('General'),
|
|
})
|
|
group.add(this.getPreferencesWidget())
|
|
page.add(group)
|
|
window.add(page)
|
|
}
|
|
}
|