better settings support

This commit is contained in:
синечка ♡ 2026-05-15 23:08:54 +03:00
parent 2dbdb7a761
commit 4627f4eb29
6 changed files with 346 additions and 107 deletions

View file

@ -1,21 +1,16 @@
:root {
/* --base_bg_color: 10;
body {
--base_bg_color: 10;
--base_bg_color_range: 10;
--base_bg_saturation: 10%;
--color_text_white: #fff;
--color_text_gray: #999;
--surface-000: #000;
--surface-100: #222;
--surface-200: #333;
--surface-300: #444;
--surface-000: var(--s000);
--surface-100: var(--s100);
--surface-200: color-mix(in srgb, var(--s200), transparent 95%);
--surface-300: color-mix(in srgb, var(--s300), transparent 85%);
--sans: 'Nunito';
--serif: 'Playfair Display';
--monospace: monospace; */
}
body {
display: flex;
height: 100vh;
width: 100vw;

View file

@ -20,7 +20,7 @@
display: flex;
align-items: center;
justify-content: center;
background: var(--surface-100);
background: var(--surface-200);
padding: 5px 10px;
border-radius: 10px 10px 0 0;
border: solid 1px var(--surface-300);
@ -28,7 +28,7 @@
user-select: none;
}
>div:hover {
background: var(--surface-200);
background: var(--surface-300);
}
>div:active {
background: var(--surface-300);
@ -45,29 +45,155 @@
}
}
#settingsui {
z-index: 12;
#settings.ov {
transform: translateX(34vw);
}
#settings {
overflow-y: auto;
overflow-x: hidden;
z-index: 1001;
position: fixed;
display: flex;
left: 5px;
bottom: 50px;
background: rgba(255,255,255,.1);
right: 0;
top: 0;
display: flex;
flex-direction: column;
padding: 10px;
border-radius: 10px;
border: solid 1px rgba(255,255,255,.1);
padding: 20px;
gap: 10px;
height: calc(100dvh - 40px);
width: 30vw;
/* background: var(--surface-100); */
/* border-left: solid 1px var(--surface-300); */
border: none;
scrollbar-color: var(--surface-300) transparent;
h2 {
>* {
transition: transform .3s, opacity .3s;
}
>.ov {
opacity: 0;
transform: translateX(34vw);
}
>.back {
margin-bottom: 10px;
cursor: pointer;
display: flex;
gap: 10px;
align-items: center;
h2 {
font-family: var(--serif);
font-weight: normal;
font-size: 25px;
}
span {
border-radius: 100px;
font-size: 25px !important;
}
}
>.back:hover {
span {
background: var(--surface-300);
}
}
>h2, >h3 {
font-family: var(--serif);
font-weight: normal;
/* margin-bottom: 5px; */
}
br {
height: 0px !important;
}
h4 {
margin-top: 10px;
>p {
font-family: var(--sans);
/* font-weight: normal; */
/* margin-bottom: 10px; */
}
.list {
display: flex;
flex-direction: row;
gap: 10px;
flex-wrap: wrap;
}
.action {
display: flex;
align-items: center;
justify-content: center;
width: fit-content;
background: var(--surface-200);
border: solid 1px var(--surface-300);
backdrop-filter: blur(10px);
border-radius: 100px;
padding: 5px 5px;
gap: 3px;
.icon {
--size: 17px;
font-size: var(--size) !important;
height: var(--size) !important;
width: var(--size) !important;
}
:not(.icon) {
font-family: var(--sans);
font-size: 14px;
padding: 0 4px;
}
}
code {
padding: 2px 3px 3px;
background: var(--surface-200);
border: solid 1px var(--surface-300);
border-radius: 5px;
}
input, textarea {
border-radius: 20px;
background: var(--surface-200);
padding: 10px;
border: solid 1px var(--surface-300);
outline: none;
resize: vertical;
font-family: var(--monospace);
}
textarea {
border-radius: 15px !important;
height: 100dvh;
min-height: 180px;
scrollbar-color: var(--color_text_white) transparent;
text-wrap-mode: wrap;
word-wrap: break-word;
word-break: break-all;
}
input::placeholder, textarea::placeholder {
color: var(--color_text_gray);
}
.action:hover {
cursor: pointer;
background: var(--surface-300)
}
.surface {
background: var(--surface-200);
border: solid 1px var(--surface-300);
backdrop-filter: blur(10px);
/* padding: 10px; */
border-radius: 15px;
overflow: hidden;
display: flex;
flex-direction: column;
.setting_entry:nth-child(n+2) {
border-top: solid 1px var(--surface-300);
}
}
.setting_entry {
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px 11px;
padding-right: 6px;
cursor: pointer;
.icon {
color: var(--color_text_gray);
}
:not(.icon) {
font-family: var(--sans);
}
}
.setting_entry:hover {
background: var(--surface-200);
}
}

View file

@ -68,8 +68,4 @@ searcher = () => {
}
document.querySelector('#search_ddd').addEventListener('change', find)
document.querySelector('#search_ddd').addEventListener('input', (e) => {proceed(e.target.value.trim())})
setInterval(() => {
document.querySelector('#search_ddd').focus()
proceed(document.querySelector('#search_ddd').value.trim())
}, 100);
}

View file

@ -1,11 +1,13 @@
window.addEventListener('DOMContentLoaded', async () => {
search_focus.enable()
select('.settings_visual_help').overwrite(
$.div(
{onclick: () => settings.open()},
{onclick: () => settings.start()},
$.span('Open settings'),
Icons.settings({fill: true, size: 15}),
)
)
if (getFromStorage('active')?.hide_clock == true) clock()
if (storage.get('active')?.hide_clock == true) clock()
preset.load(storage.get('_active') || 'Default')
searcher()
})

View file

@ -1,55 +1,167 @@
const settings = {
icons: {
open: `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M422.46-81.87q-23.2 0-40.29-15.35-17.08-15.35-20.08-38.04l-10-73.74q-11.09-4.78-22.79-11.08-11.69-6.29-21.26-13.09l-68.26 28q-21.45 9.24-43.15 1.87t-33.67-27.57l-58.05-100.87q-11.98-19.96-7.11-42.53 4.87-22.58 23.33-37.06l59.76-45.5q-.76-5.54-.76-10.58V-480q0-5.04.25-11.09.25-6.04 1.01-14.08l-59.26-43.76q-18.7-14.48-23.7-36.81-5-22.33 6.98-43.02l57.55-100.13q11.97-19.96 33.8-27.45 21.83-7.49 43.28 1.75l69.98 29q8.57-6.8 18.9-12.73 10.34-5.92 23.17-11.2l10-75.98q3-22.93 20.33-38.28 17.34-15.35 40.54-15.35h114.58q23.2 0 40.29 15.35 17.08 15.35 20.08 38.28l10 74.48q12.09 4.78 22.29 10.95 10.19 6.18 19.76 14.48l70.26-29q21.45-9.24 43.15-1.75t33.67 27.45l57.55 100.13q11.98 20.19 6.98 42.77-5 22.58-23.7 37.06l-62 45.76q.76 6.04.76 10.83V-480q0 7.54-.12 12.84-.12 5.29-1.14 10.83l61 44.76q18.7 14.48 23.7 37.06 5 22.58-6.98 42.77l-58.05 100.87q-11.97 19.96-33.8 27.45-21.83 7.49-43.28-1.75l-68.48-29q-8.07 6.3-17.4 11.84-9.34 5.55-24.17 12.83l-10 74.24q-3 22.69-20.08 38.04-17.09 15.35-40.29 15.35H422.46ZM478.78-345q56 0 95.5-39.5t39.5-95.5q0-56-39.5-95.5t-95.5-39.5q-56.26 0-95.63 39.5T343.78-480q0 56 39.37 95.5t95.63 39.5Z"/></svg>`,
close: `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M480-419.35 289.33-228.67Q276.65-216 259-216.25t-30.33-12.92q-12.17-12.68-11.92-30.08t12.42-29.58L419.35-480 229.17-671.17Q217-683.35 217-700.75t12.17-30.08q12.18-12.67 29.83-12.92t30.33 12.42L480-540.65l190.67-190.68Q683.35-744 701-743.75t30.33 12.92q12.17 12.68 11.92 30.08t-12.42 29.58L540.65-480l190.18 191.17Q743-276.65 743-259.25t-12.17 30.08Q718.65-216.5 701-216.25t-30.33-12.42L480-419.35Z"/></svg>`
const search_focus = {
id: null,
paused: false,
enable: () => {
search_focus.paused = false
if (search_focus.id) return
search_focus.id = setInterval(() => {
if (search_focus.paused) return
if (!search_focus.id) return
document.querySelector('#search_ddd').focus()
console.log(search_focus.id)
// proceed(document.querySelector('#search_ddd').value.trim())
}, 100)
},
styles: {
'base_bg_color': [0, 360, 'Color', ''],
'base_bg_saturation': [0, 100, 'Saturation', '%'],
'base_bg_color_range': [0, 180, 'Range', ''],
},
set_style: (name, value) => {
setToStorage(`theme_${name}`, value)
const bg = document.querySelector('#background')
bg.style.setProperty(`--${name}`, value)
bg.style.display = 'none'
setTimeout(async () => {
bg.style.display = 'block'
},)
},
init: async () => {
document.querySelector('#settingsbutton').innerHTML = settings.icons.open
document.querySelector('#settingsbutton').onclick = () => settings.open()
Object.keys(settings.styles).map(
key => {
const v = getFromStorage(`theme_${key}`)
if (!v) settings.set_style(key, `11${settings.styles[key][3]}`)
else settings.set_style(key, v)
}
)
},
open: async () => {
const ret = name => parseInt(document.querySelector('#background').style.getPropertyValue(`--${name}`).trim().replace('%', ''))
const setter = (name, trail = '') => (e) => settings.set_style(name, `${e.target.value}${trail}`)
const state = (name, trail = '') => {return {value: ret(name), oninput: setter(name, trail)}}
document.body.appendChild($.div(
{id: 'settingsui'},
$.h2('Settings'),
...Object.keys(settings.styles).map(key => {
const d = settings.styles[key]
return $.div(
$.h4(d[2]),
$.input({type: 'range', min: d[0], max: d[1], ...state(key, d[3])})
)
})
))
document.querySelector('#settingsbutton').innerHTML = settings.icons.close
document.querySelector('#settingsbutton').onclick = () => {
document.querySelector('#settingsui').remove()
settings.init()
}
disable: () => {
search_focus.paused = true
}
}
const settings = {
views: [],
current: null,
back: async () => {
settings.current = settings.views.pop()
if (!settings.current) {
selectAll('#settings > *').map(e => e.element.classList.add('ov'))
await sleep(.2)
settings.stop()
} else {
settings._open(settings.current())
}
},
_open: async elements => {
selectAll('#settings > *').map(e => e.element.classList.add('ov'))
await sleep(.2)
select('#settings').overwrite(...elements)
selectAll('#settings > *').map(e => e.element.classList.add('ov'))
requestAnimationFrame(() => selectAll('#settings > *').map(e => e.element.classList.remove('ov')))
},
}
next: async fn => {
settings.views.push(settings.current)
settings.current = fn
settings._open(fn())
},
back_button: (title, icon = Icons.arrow_back) => $.div(
{onclick: settings.back, class: 'back'},
icon(),
$.h2(title),
),
start: () => {
settings.views = []
settings.current = null
select('body').append(
$.div({id: 'settings'})
)
search_focus.disable()
settings.next(settings.main)
},
stop: () => {
select('#settings').remove()
search_focus.enable()
},
main: () => [
settings.back_button('Settings', Icons.close),
$.div(
{class: 'surface'},
$.div(
{class: 'setting_entry', onclick: () => settings.next(settings.basic)},
$.span('Basic settings'),
Icons.arrow_right()
),
$.div(
{class: 'setting_entry', onclick: () => settings.next(settings.bangs)},
$.span('Bangs editor'),
Icons.arrow_right()
),
$.div(
{class: 'setting_entry', onclick: () => settings.next(settings.customization)},
$.span('Customization'),
Icons.arrow_right()
),
)
],
basic: () => [
settings.back_button('Basic Settings'),
],
bangs: () => [
settings.back_button('Bangs editor'),
$.p('Here are your custom bangs, that will override default one from DuckDuckGo'),
$.div(
{class: 'list'},
$.div(
{class: 'action', onclick: () => settings.next(() => settings.edit_bang(false))},
Icons.add_2(),
),
),
$.div(
{class: 'surface'},
...bangs_override.toReversed().map(b => $.div(
{class: 'setting_entry', onclick: () => settings.next(() => settings.edit_bang(b))},
$.span(b.name),
Icons.arrow_right()
))
)
],
edit_bang: bang_data => {
const index = bangs_override.findIndex(b => b === bang_data)
/** @type {Bang} */
state.bang = bang_data || {
name: '',
keyword: '',
url: ''
}
return [
settings.back_button('Edit Bang'),
$.h3('Name'),
$.input({value: state.bang.name, placeholder: 'Bang name', onchange: (e) => state.bang.name = e.target.value.trim()}),
$.div({style: 'height: 10px'}),
$.h3('Keyword'),
$.p('Add a short keyword for your bang, e.g. ', $.code('google')),
$.input({value: state.bang.keyword, placeholder: 'Bang keyword', onchange: (e) => state.bang.keyword = e.target.value.trim()}),
$.div({style: 'height: 10px'}),
$.h3('URL'),
$.p('Add a url for your bang with ', $.code('{{{s}}}'), ' string, that will be replaced with the search query'),
$.textarea({value: state.bang.url, placeholder: 'Bang URL', onchange: (e) => state.bang.url = e.target.value.trim()}, state.bang.url),
$.div(
{class: 'list'},
$.div(
{class: 'action', onclick: () => {
if (state.bang.name.length && state.bang.keyword.length && state.bang.url.length) {
index != -1 ? bangs_override[index] = state.bang : bangs_override.push(state.bang)
storage.set('_bangs', bangs_override)
settings.back()
} else {
alert('Please fill in all fields')
}
}},
$.span('Save'),
),
bang_data ? $.div(
{class: 'action', onclick: () => {
if (confirm('Are you sure you want to delete this bang?')) {
bangs_override.splice(index, 1)
storage.set('_bangs', bangs_override)
settings.back()
}
}},
$.span('Delete'),
) : null
),
]
}
}
const state = {
/** @type {Bang} */
bang: null,
/** @type {string} */
search_url: null,
}
// debug
sleep(.3).then(() => settings.start())

View file

@ -34,18 +34,16 @@ const storage = {
* @typedef {Object} Preset
* @prop {number} version
* @prop {string} name
* @prop {bool} disable_clock
* @prop {bool} disable_animations
* @prop {"default" | "url" | "color" | "gradient"} background_type // TODO: gradient
* @prop {number} base_bg_color
* @prop {number} base_bg_saturation
* @prop {number} base_bg_color_range
* @prop {string} search_url
* @prop {bool} display_suggestions
* @prop {bool} display_history
* @prop {string} font_sans
// * @prop {string} font_sans_size
* @prop {string} font_serif
// * @prop {string} font_serif_size
* @prop {string} font_monospace
// * @prop {string} font_monospace_size
* @prop {string} color_text_white
* @prop {string} color_text_gray
* @prop {string} s000
@ -114,10 +112,10 @@ const preset = {
)
}
const style_override = {
s000: 'surface-000',
s100: 'surface-100',
s200: 'surface-200',
s300: 'surface-300',
// s000: 'surface-000',
// s100: 'surface-100',
// s200: 'surface-200',
// s300: 'surface-300',
font_sans: 'sans',
font_serif: 'serif',
font_monospace: 'monospace',
@ -145,34 +143,44 @@ const preset = {
default: () => { return {
name: 'Defualt',
version: preset.current_version,
disable_clock: false,
disable_animations: false,
// disable_clock: false,
// disable_animations: false,
background_type: 'default',
base_bg_color: 10,
base_bg_saturation: 10,
base_bg_brightness: 10,
base_bg_color_range: 10,
search_url: 'https://www.google.com/search?q={{{s}}}',
display_suggestions: false,
display_history: false,
// search_url: 'https://www.google.com/search?q={{{s}}}',
// display_suggestions: false,
// display_history: false,
font_sans: 'Nunito',
font_serif: 'Playfair Display',
font_monospace: 'monospace',
color_text_white: '#fff',
color_text_gray: '#999',
s000: '#000',
s100: '#222',
s200: '#333',
s300: '#444',
s100: '#fff',
s200: '#fff',
s300: '#fff',
}}
}
const defaults = {
bangs: [
{name: 'Test bang', keyword: 'test_bang', url: 'https://www.google.com/search?q={{{s}}}'},
{name: 'Google Search AI', keyword: 'ai', url: 'https://www.google.com/search?q={{{s}}}&sourceid=chrome&ie=UTF-8&amc=1&oq={{{s}}}&udm=50&aep=109&cud='}
],
search_engine: 'https://www.google.com/search?q={{{s}}}'
}
/**
* @typedef {Object} Bang
* @prop {string} keyword
* @prop {string} name
* @prop {string} url
*/
var bangs_override = [
{name: 'Google Search AI', keyword: 'ai', url: 'https://www.google.com/search?q={{{s}}}&sourceid=chrome&ie=UTF-8&amc=1&oq={{{s}}}&udm=50&aep=109&cud='}
]
/** @type {Bang[]} */
var bangs_override = storage.get('_bangs') || defaults.bangs
/** @type {string} */
var search_engine = storage.get('_search') || defaults.search_engine