diff --git a/src/css/global.css b/src/css/global.css index 022f59d..cb61818 100644 --- a/src/css/global.css +++ b/src/css/global.css @@ -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; diff --git a/src/css/settings.css b/src/css/settings.css index b6fd470..bf7f612 100644 --- a/src/css/settings.css +++ b/src/css/settings.css @@ -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); } } \ No newline at end of file diff --git a/src/js/builtin.js b/src/js/builtin.js index 7aebd4a..e92ba13 100644 --- a/src/js/builtin.js +++ b/src/js/builtin.js @@ -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); } \ No newline at end of file diff --git a/src/js/main.js b/src/js/main.js index 50df5e8..51c9119 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -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() }) diff --git a/src/js/settings.js b/src/js/settings.js index 8647fae..25ad111 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -1,55 +1,167 @@ -const settings = { - icons: { - open: ``, - close: `` +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'))) + }, -} \ No newline at end of file + 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()) diff --git a/src/js/storage.js b/src/js/storage.js index 55c07c5..d231911 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -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='} -] \ No newline at end of file +/** @type {Bang[]} */ +var bangs_override = storage.get('_bangs') || defaults.bangs + +/** @type {string} */ +var search_engine = storage.get('_search') || defaults.search_engine \ No newline at end of file