├── 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 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 295 | 296 | 297 | 298 | 300 | 301 | 302 | 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 | })() --------------------------------------------------------------------------------