├── images
├── sky-theme16.png
├── sky-theme32.png
├── sky-theme64.png
└── sky-theme128.png
├── popup.html
├── style.css
├── README.md
├── manifest.json
├── background.js
└── popup.js
/images/sky-theme16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamedamz/sky-theme/HEAD/images/sky-theme16.png
--------------------------------------------------------------------------------
/images/sky-theme32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamedamz/sky-theme/HEAD/images/sky-theme32.png
--------------------------------------------------------------------------------
/images/sky-theme64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamedamz/sky-theme/HEAD/images/sky-theme64.png
--------------------------------------------------------------------------------
/images/sky-theme128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamedamz/sky-theme/HEAD/images/sky-theme128.png
--------------------------------------------------------------------------------
/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | #--h-sky-theme-popup {
2 | display: grid;
3 | grid-template-columns: repeat(3, 1fr);
4 | width: 160px;
5 | }
6 |
7 | :root {
8 | --cr-theme-icon-size: 50px;
9 | }
10 |
11 | .theme {
12 | cursor: pointer;
13 | display: block;
14 | }
15 |
16 | .theme, svg {
17 | height: var(--cr-theme-icon-size);
18 | width: var(--cr-theme-icon-size);
19 | }
20 |
21 | .ring {
22 | fill: #a3c7f6;
23 | visibility: hidden;
24 | }
25 |
26 | .checkMark {
27 | visibility: hidden;
28 | }
29 |
30 | .theme.selected .ring, .theme.selected .checkMark {
31 | visibility: visible;
32 | }
33 |
34 | .checkMark circle {
35 | fill: #1a73e8;
36 | }
37 |
38 | .checkMark path {
39 | fill: white;
40 | }
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sky Theme
2 | It's a google chrome extension for customizing SkyRoom theme.
3 | ## Download
4 | Download the latest version from [here](https://github.com/Hamedamz/sky-theme/releases) and extract it.
5 | ## Install
6 | 1. Open the Extension Management page by navigating to `chrome://extensions`.
7 | - Alternatively, open this page by clicking on the Extensions menu button and selecting **Manage Extensions** at the bottom of the menu.
8 | - Alternatively, open this page by clicking on the Chrome menu, hovering over **More Tools** then selecting **Extensions**
9 | 2. Enable Developer Mode by clicking the toggle switch next to **Developer mode**.
10 | 3. Click the **Load unpacked** button and select the extension directory.
11 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Sky Theme",
3 | "description": "Customize your skyroom",
4 | "version": "1.0",
5 | "manifest_version": 3,
6 | "background": {
7 | "service_worker": "background.js"
8 | },
9 | "content_scripts": [
10 | {
11 | "matches": ["https://vc.sharif.edu/*"],
12 | "js": ["popup.js"]
13 | }
14 | ],
15 | "permissions": ["storage", "activeTab", "scripting"],
16 | "action": {
17 | "default_popup": "popup.html",
18 | "default_icon": {
19 | "16": "/images/sky-theme16.png",
20 | "32": "/images/sky-theme32.png",
21 | "64": "/images/sky-theme64.png",
22 | "128": "/images/sky-theme128.png"
23 | }
24 | },
25 | "icons": {
26 | "16": "/images/sky-theme16.png",
27 | "32": "/images/sky-theme32.png",
28 | "64": "/images/sky-theme64.png",
29 | "128": "/images/sky-theme128.png"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/background.js:
--------------------------------------------------------------------------------
1 | let themes = [
2 | {
3 | name: 'default',
4 | bgColor: '#ddd',
5 | bgColorFront: '#fff',
6 | bgColorBack: '#ddd',
7 | textColor: '#fff',
8 | borderColor: 'transparent',
9 | borderBottomColor: 'transparent',
10 | },
11 |
12 | {
13 | name: 'dark',
14 | bgColor: '#353535',
15 | bgColorFront: '#4f4f4f',
16 | bgColorBack: '#202020',
17 | textColor: '#efefef',
18 | borderColor: 'transparent',
19 | borderBottomColor: 'transparent',
20 | },
21 |
22 | {
23 | name: 'gray',
24 | bgColor: '#2b373d',
25 | bgColorFront: '#445760',
26 | bgColorBack: '#222b30',
27 | textColor: '#e0e4e6',
28 | borderColor: 'transparent',
29 | borderBottomColor: 'transparent',
30 | },
31 |
32 | {
33 | name: 'violetgray',
34 | bgColor: '#322e47',
35 | bgColorFront: '#544f71',
36 | bgColorBack: '#272337',
37 | textColor: '#e2e0e6',
38 | borderColor: 'transparent',
39 | borderBottomColor: 'transparent',
40 | },
41 |
42 | {
43 | name: 'bluegray',
44 | bgColor: '#2a394c',
45 | bgColorFront: '#475d7b',
46 | bgColorBack: '#212d3b',
47 | textColor: '#e0e2e6',
48 | borderColor: 'transparent',
49 | borderBottomColor: 'transparent',
50 | },
51 |
52 | {
53 | name: 'tealgray',
54 | bgColor: '#273c3f',
55 | bgColorFront: '#3f5f64',
56 | bgColorBack: '#1f3033',
57 | textColor: '#e0e4e6',
58 | borderColor: 'transparent',
59 | borderBottomColor: 'transparent',
60 | },
61 |
62 | {
63 | name: 'violet',
64 | bgColor: '#462a68',
65 | bgColorFront: '#6d41a1',
66 | bgColorBack: '#3d255b',
67 | textColor: '#e3e0e6',
68 | borderColor: 'transparent',
69 | borderBottomColor: 'transparent',
70 | },
71 |
72 | {
73 | name: 'ocean',
74 | bgColor: '#0d3562',
75 | bgColorFront: '#14539a',
76 | bgColorBack: '#0b2c51',
77 | textColor: '#e0e3e6',
78 | borderColor: 'transparent',
79 | borderBottomColor: 'transparent',
80 | },
81 |
82 | {
83 | name: 'teal',
84 | bgColor: '#023a3e',
85 | bgColorFront: '#055b62',
86 | bgColorBack: '#012a2d',
87 | textColor: '#e0e6e6',
88 | borderColor: 'transparent',
89 | borderBottomColor: 'transparent',
90 | },
91 |
92 | {
93 | name: 'forest',
94 | bgColor: '#18391a',
95 | bgColorFront: '#275d2b',
96 | bgColorBack: '#122b14',
97 | textColor: '#e0e6e0',
98 | borderColor: 'transparent',
99 | borderBottomColor: 'transparent',
100 | },
101 |
102 | {
103 | name: 'rose',
104 | bgColor: '#6d1212',
105 | bgColorFront: '#a71c1c',
106 | bgColorBack: '#5c0f0f',
107 | textColor: '#e6e0e0',
108 | borderColor: 'transparent',
109 | borderBottomColor: 'transparent',
110 | },
111 |
112 | {
113 | name: 'magenta',
114 | bgColor: '#660d33',
115 | bgColorFront: '#a0144f',
116 | bgColorBack: '#560b2b',
117 | textColor: '#e6e0e2',
118 | borderColor: 'transparent',
119 | borderBottomColor: 'transparent',
120 | }
121 | ]
122 |
123 | chrome.runtime.onInstalled.addListener(() => {
124 | chrome.storage.sync.set({ themes });
125 | chrome.storage.sync.set({ selectedTheme: themes[3] });
126 | chrome.storage.sync.set({ isDark: false });
127 | chrome.storage.sync.set({ isMirror: false });
128 | });
129 |
--------------------------------------------------------------------------------
/popup.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | if(!document.getElementById('--h-sky-theme-popup')) {
3 | injectTheme()
4 | setDarkSlideShow()
5 | setMirroredWebcam()
6 | return
7 | }
8 |
9 | //themes
10 | chrome.storage.sync.get('themes', ({ themes }) => {
11 | chrome.storage.sync.get('selectedTheme', ({ selectedTheme }) => {
12 | themes.forEach(theme => {
13 | const themeIcon = renderThemeIcon(theme)
14 |
15 | if (selectedTheme && selectedTheme.name === theme.name) {
16 | themeIcon.classList.add('selected')
17 | changeTheme(themeIcon, theme)
18 | }
19 |
20 | const container = document.getElementById('--h-sky-theme-popup')
21 | container.appendChild(themeIcon)
22 | })
23 | })
24 | })
25 |
26 | //dark
27 | const darkCheckbox = document.getElementById('--h-dark-checkbox')
28 |
29 | chrome.storage.sync.get('isDark', ({ isDark }) => {
30 | darkCheckbox.checked = isDark
31 | changeDarkMode()
32 |
33 | darkCheckbox.addEventListener('change', changeDarkMode)
34 | })
35 |
36 | async function changeDarkMode() {
37 | chrome.storage.sync.set({ isDark: darkCheckbox.checked })
38 |
39 | let [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
40 |
41 | chrome.scripting.executeScript({
42 | target: { tabId: tab.id },
43 | function: setDarkSlideShow,
44 | });
45 | }
46 |
47 | //mirror
48 | const mirrorCheckbox = document.getElementById('--h-mirror-checkbox')
49 |
50 | chrome.storage.sync.get('isMirror', ({ isMirror }) => {
51 | mirrorCheckbox.checked = isMirror
52 | changeMirror()
53 |
54 | mirrorCheckbox.addEventListener('change', changeMirror)
55 | })
56 |
57 | async function changeMirror() {
58 | chrome.storage.sync.set({ isMirror: mirrorCheckbox.checked })
59 |
60 | let [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
61 |
62 | chrome.scripting.executeScript({
63 | target: { tabId: tab.id },
64 | function: setMirroredWebcam,
65 | });
66 | }
67 |
68 | async function changeTheme(element, theme) {
69 | Array.from(document.getElementsByClassName('theme'))
70 | .forEach((element) => element.classList.remove('selected'))
71 | element.classList.add('selected')
72 |
73 | chrome.storage.sync.set({ selectedTheme: theme })
74 |
75 | let [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
76 |
77 | chrome.scripting.executeScript({
78 | target: { tabId: tab.id },
79 | function: injectTheme,
80 | });
81 | }
82 |
83 |
84 | // the body of this function must be self contained
85 |
86 | function setMirroredWebcam() {
87 | chrome.storage.sync.get('isMirror', ({ isMirror }) => {
88 | if (isMirror) {
89 | document.body.classList.add('--h-sky-theme-mirror')
90 | } else {
91 | document.body.classList.remove('--h-sky-theme-mirror')
92 | }
93 | })
94 | }
95 |
96 | // the body of this function must be self contained
97 |
98 | function setDarkSlideShow() {
99 | chrome.storage.sync.get('isDark', ({ isDark }) => {
100 | if (isDark) {
101 | document.body.classList.add('--h-sky-theme-dark')
102 | } else {
103 | document.body.classList.remove('--h-sky-theme-dark')
104 | }
105 | })
106 | }
107 |
108 | // the body of this function must be self contained
109 |
110 | function injectTheme() {
111 | chrome.storage.sync.get('selectedTheme', ({ selectedTheme: theme }) => {
112 | const css = theme.name === 'default' ? '' :
113 | `:root {
114 | --bg-color: ${theme.bgColor};
115 | --bg-color-front: ${theme.bgColorFront};
116 | --bg-color-back: ${theme.bgColorBack};
117 | --text-color: ${theme.textColor};
118 | --border-color: ${theme.borderColor};
119 | --border-bottom-color: ${theme.borderBottomColor};
120 | }
121 |
122 | .block, .menu-items, .dialog, .board, .list, .chat .emoji-list, .chat .pinned-message {
123 | background-color: var(--bg-color-front);
124 | }
125 |
126 | .chat .pinned-message {
127 | filter: brightness(1.1);
128 | }
129 |
130 | .block, .menu-items, .dialog {
131 | border: 1px solid var(--bg-color-front);
132 | border-radius: 6px !important;
133 | }
134 |
135 | .menu-items, .dialog {
136 | -webkit-box-shadow: 0px 4px 12px 0 rgba(0, 0, 0, 0.45);
137 | box-shadow: 0px 4px 12px 0 rgba(0, 0, 0, 0.45);
138 | }
139 |
140 | .menu-items li:hover, .list .list-item:hover {
141 | color: #fff;
142 | background-color: rgba(255, 255, 255, 0.1);
143 | }
144 |
145 | .list.no-icon .list-item.selected {
146 | border: none;
147 | background: var(--bg-color-back);
148 | }
149 |
150 | .menu-items li.separator {
151 | border-top: 2px groove rgba(255, 255, 255, .1);
152 | }
153 |
154 | .dialog>.dialog-header {
155 | border-bottom: 2px groove rgba(255, 255, 255, .1);
156 | }
157 |
158 | .entry, .input, input, select, textarea {
159 | background-color: var(--bg-color-back);
160 | border-radius: 4px;
161 | border: none;
162 | outline: none;
163 | }
164 |
165 | .chat .commands-box, .chat .commands-box .preview-box {
166 | background: var(--bg-color-back);
167 | border-radius: 4px;
168 | }
169 |
170 | .btn, button {
171 | border-radius: 4px;
172 | }
173 |
174 | .nav .nav-item {
175 | background-color: rgba(255,255,255,.1);
176 | border: 1px solid rgba(255,255,255,.3);
177 | }
178 |
179 | .nav .nav-item:hover, .btn-flat:hover {
180 | background-color: rgba(255,255,255,.2);
181 | border: 1px solid rgba(255,255,255,.4);
182 | }
183 |
184 | .dropdown .dropdown-toggle:hover {
185 | background: rgba(255,255,255,.1);
186 | }
187 |
188 | .dropdown .dropdown-toggle:active, .dropdown .dropdown-toggle:focus {
189 | background: rgba(255,255,255,.2);
190 | }
191 |
192 | header {
193 | background: var(--bg-color-front);
194 | border-bottom: 1px solid transparent;
195 | }
196 |
197 | .users .user-row {
198 | border-radius: 4px;
199 | }
200 |
201 | .users .user-row.focused, .users .user-row:hover {
202 | background-color: rgba(255, 255, 255, .1);
203 | }
204 |
205 | .table-hover>tbody>tr:hover {
206 | background-color: rgba(255, 255, 255, .1);
207 | }
208 |
209 | .table-hover>tbody>tr.selected {
210 | background-color: rgba(255, 255, 255, .2);
211 | }
212 |
213 | .settings .notifications button.checkbox>.icon-off:hover {
214 | fill: rgba(255, 255, 255, .5);
215 | }
216 |
217 | .settings .notifications button.checkbox>.icon-off {
218 | fill: rgba(255, 255, 255, .3);
219 | }
220 |
221 | .table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td {
222 | border-bottom: 1px solid rgba(255, 255, 255, .1);
223 | }
224 |
225 | .nav-tabs, .table-condensed>* {
226 | border-bottom: 1px solid rgba(255, 255, 255, .1);
227 | }
228 |
229 | body ::-webkit-scrollbar-thumb {
230 | background: rgba(255, 255, 255, .2) !important;
231 | }
232 |
233 | body ::-webkit-scrollbar-thumb:hover {
234 | background: rgba(255, 255, 255, .5) !important;
235 | }
236 |
237 | .chat .chat-msg, .chat .chat-msg .message-commands {
238 | background-color: var(--bg-color-front);
239 | }
240 |
241 | .chat .chat-msg .message-commands button:hover, .chat .pinned-message button:hover {
242 | background: rgba(255, 255, 255, .2);
243 | border-color: transparent;
244 | }
245 |
246 | .board .toolbar button.btn-on, .board .toolbar2 button.btn-on {
247 | background: rgba(255, 255, 255, .2);
248 | }
249 |
250 | .rtl .chat .chat-msg .quoted-message {
251 | border-left: none;
252 | border-right: 3px solid rgba(255, 255, 255, .3);
253 | }
254 |
255 | .chat .chat-msg .quoted-message {
256 | border-left: 3px solid rgba(255, 255, 255, .3);
257 | background: rgba(255, 255, 255, .1);
258 | }
259 | `;
260 |
261 | const darkCss = `
262 | body.--h-sky-theme-dark .slide-wrapper { filter: invert(0.9) hue-rotate(180deg); }
263 | body.--h-sky-theme-mirror video[muted] { transform: scale(-1, 1); }`
264 |
265 | let style = document.getElementById('--h-sky-theme-style')
266 | const cssTextNode = document.createTextNode(css + darkCss)
267 |
268 | if (style) {
269 | style.firstChild.replaceWith(cssTextNode);
270 | } else {
271 | style = document.createElement('style');
272 | style.id = '--h-sky-theme-style';
273 | style.appendChild(cssTextNode)
274 | document.body.appendChild(style);
275 | }
276 | });
277 | }
278 |
279 | function renderThemeIcon(theme) {
280 | const svg = `
281 |
303 | `
304 |
305 | const themeIcon = document.createElement('div')
306 | themeIcon.innerHTML = svg
307 | themeIcon.classList.add('theme')
308 | themeIcon.addEventListener('click', () => changeTheme(themeIcon, theme))
309 |
310 | return themeIcon
311 | }
312 | })()
--------------------------------------------------------------------------------