Files: 90fd465da992b9a0c6ce19b5cbd52d9eff064bd3 / modules / theme.js
4663 bytesRaw
1 | var h = require('hyperscript') |
2 | var pull = require('pull-stream') |
3 | var plugs = require('../plugs') |
4 | var cat = require('pull-cat') |
5 | |
6 | var sbot_links2 = plugs.first(exports.sbot_links2 = []) |
7 | var avatar_name = plugs.first(exports.avatar_name = []) |
8 | var blob_url = require('../plugs').first(exports.blob_url = []) |
9 | |
10 | var defaultTheme = { |
11 | id: '&JFa42U6HtPm9k+s+AmpDIAoTJJI/PzoRC/J/WCfduDY=.sha256', |
12 | name: 'patchbay-minimal.css' |
13 | } |
14 | |
15 | var next = 'undefined' === typeof setImmediate ? setTimeout : setImmediate |
16 | |
17 | var link = document.head.appendChild(h('link', {rel: 'stylesheet'})) |
18 | var activeTheme |
19 | |
20 | function useTheme(id) { |
21 | activeTheme = id |
22 | link.href = id ? blob_url(id) : '' |
23 | var forms = [].slice.call(document.querySelectorAll('.themes__form')) |
24 | forms.forEach(updateForm) |
25 | |
26 | var radios = [].slice.call(document.querySelectorAll('input[type=radio]')) |
27 | radios.forEach(function (radio) { |
28 | radio.checked = (radio.value === activeTheme) |
29 | }) |
30 | } |
31 | |
32 | function useSavedTheme() { |
33 | //enable setting "NONE" as your theme, and having that persist. |
34 | useTheme(localStorage.themeId == null ? defaultTheme.id : localStorage.themeId) |
35 | } |
36 | |
37 | next(useSavedTheme) |
38 | |
39 | function themes() { |
40 | return cat([ |
41 | pull.values([ |
42 | { |
43 | id: '', |
44 | name: 'none', |
45 | feed: '' |
46 | }, |
47 | defaultTheme, |
48 | ]), |
49 | pull( |
50 | sbot_links2({ |
51 | query: [ |
52 | {$filter: {rel: ['mentions', {$prefix: 'patchbay-'}]}}, |
53 | {$filter: {dest: {$prefix: '&'}}}, |
54 | {$map: {id: 'dest', feed: 'source', name: ['rel', 1]}} |
55 | ], |
56 | live: true, |
57 | sync: false, |
58 | }), |
59 | pull.filter(function (link) { |
60 | return /\.css$/.test(link.name) |
61 | }) |
62 | ) |
63 | ]) |
64 | } |
65 | |
66 | function onRadioClick(e) { |
67 | if (this.checked) useTheme(this.value) |
68 | } |
69 | |
70 | function updateForm(form) { |
71 | var same = localStorage.themeId === activeTheme |
72 | form.querySelector('.themes__id').value = activeTheme |
73 | form.querySelector('.themes__reset').disabled = same |
74 | form.querySelector('.themes__submit').disabled = same |
75 | return form |
76 | } |
77 | |
78 | function renderTheme(link) { |
79 | return h('div.theme', |
80 | h('input', {type: 'radio', name: 'theme', |
81 | value: link.id, onclick: onRadioClick, |
82 | checked: link.id === activeTheme |
83 | }), |
84 | link.id ? h('a', {href: '#'+link.id}, link.name) : link.name, ' ', |
85 | link.feed ? h('a', {href: '#'+link.feed}, avatar_name(link.feed)) : '' |
86 | ) |
87 | } |
88 | |
89 | function insertAfter(parentNode, newNode, referenceNode) { |
90 | var nextSibling = referenceNode && referenceNode.nextSibling |
91 | if (nextSibling) parentNode.insertBefore(newNode, nextSibling) |
92 | else parentNode.appendChild(newNode) |
93 | } |
94 | |
95 | function theme_view() { |
96 | var themeInput |
97 | var themesList = h('form.themes__list') |
98 | var themesPerFeed = {/* feedid: {blobid||name: theme} */} |
99 | |
100 | pull( |
101 | themes(), |
102 | pull.drain(function (theme) { |
103 | var map = themesPerFeed[theme.feed] || (themesPerFeed[theme.feed] = {}) |
104 | // replace old theme |
105 | var prevByName = map[theme.name] |
106 | var prevById = map[theme.id] |
107 | theme.el = renderTheme(theme) |
108 | map[theme.name] = theme |
109 | map[theme.id] = theme |
110 | if (prevById) { |
111 | // remove theme which is having its id reused |
112 | themesList.removeChild(prevById.el) |
113 | // prevById.el.appendChild(document.createTextNode(' (renamed)')) |
114 | if (prevById === prevByName) { |
115 | prevByName = null |
116 | } |
117 | } |
118 | if (prevByName) { |
119 | // update theme |
120 | if (prevByName.id === localStorage.themeId |
121 | || prevByName.id === activeTheme) { |
122 | // keep old version because the user is still using it |
123 | prevByName.el.appendChild(document.createTextNode(' (old)')) |
124 | insertAfter(themesList, theme.el, prevByName.el) |
125 | } else { |
126 | // replace old version |
127 | themesList.replaceChild(theme.el, prevByName.el) |
128 | } |
129 | } else { |
130 | // show new theme |
131 | themesList.appendChild(theme.el) |
132 | } |
133 | }, function (err) { |
134 | if (err) console.error(err) |
135 | }) |
136 | ) |
137 | |
138 | return h('div.column.scroll-y', h('div', |
139 | updateForm(h('form.themes__form', {onsubmit: onsubmit, onreset: onreset}, |
140 | themeInput = h('input.themes__id', {placeholder: 'theme id', |
141 | value: link.href}), ' ', |
142 | h('input.themes__reset', {type: 'reset'}), ' ', |
143 | h('input.themes__submit', {type: 'submit', value: 'Save'}))), |
144 | themesList |
145 | )) |
146 | |
147 | function onsubmit(e) { |
148 | e.preventDefault() |
149 | useTheme(localStorage.themeId = themeInput.value) |
150 | } |
151 | |
152 | function onreset(e) { |
153 | e.preventDefault() |
154 | useSavedTheme() |
155 | } |
156 | } |
157 | |
158 | exports.menu_items = function () { |
159 | return h('a', {href:'#/theme'}, '/theme') |
160 | } |
161 | |
162 | exports.screen_view = function (path) { |
163 | if(path === '/theme') return theme_view() |
164 | } |
165 |
Built with git-ssb-web