diff options
Diffstat (limited to 'client/src/app/core/theme')
-rw-r--r-- | client/src/app/core/theme/theme.service.ts | 124 |
1 files changed, 94 insertions, 30 deletions
diff --git a/client/src/app/core/theme/theme.service.ts b/client/src/app/core/theme/theme.service.ts index 50c19ecac..ad59c203b 100644 --- a/client/src/app/core/theme/theme.service.ts +++ b/client/src/app/core/theme/theme.service.ts | |||
@@ -1,41 +1,105 @@ | |||
1 | import { Injectable } from '@angular/core' | 1 | import { Injectable } from '@angular/core' |
2 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | 2 | import { AuthService } from '@app/core/auth' |
3 | import { ServerService } from '@app/core/server' | ||
4 | import { environment } from '../../../environments/environment' | ||
5 | import { PluginService } from '@app/core/plugins/plugin.service' | ||
6 | import { ServerConfigTheme } from '@shared/models' | ||
3 | 7 | ||
4 | @Injectable() | 8 | @Injectable() |
5 | export class ThemeService { | 9 | export class ThemeService { |
6 | private theme = document.querySelector('body') | 10 | |
7 | private darkTheme = false | 11 | private oldThemeName: string |
8 | private previousTheme: { [ id: string ]: string } = {} | 12 | private themes: ServerConfigTheme[] = [] |
9 | 13 | ||
10 | constructor () { | 14 | constructor ( |
11 | // initialise the alternative theme with dark theme colors | 15 | private auth: AuthService, |
12 | this.previousTheme['mainBackgroundColor'] = '#111111' | 16 | private pluginService: PluginService, |
13 | this.previousTheme['mainForegroundColor'] = '#fff' | 17 | private server: ServerService |
14 | this.previousTheme['submenuColor'] = 'rgb(32,32,32)' | 18 | ) {} |
15 | this.previousTheme['inputColor'] = 'gray' | 19 | |
16 | this.previousTheme['inputPlaceholderColor'] = '#fff' | 20 | initialize () { |
17 | 21 | this.server.configLoaded | |
18 | this.darkTheme = (peertubeLocalStorage.getItem('theme') === 'dark') | 22 | .subscribe(() => { |
19 | if (this.darkTheme) this.toggleDarkTheme(false) | 23 | this.injectThemes() |
24 | |||
25 | this.listenUserTheme() | ||
26 | }) | ||
27 | } | ||
28 | |||
29 | private injectThemes () { | ||
30 | this.themes = this.server.getConfig().theme.registered | ||
31 | |||
32 | console.log('Injecting %d themes.', this.themes.length) | ||
33 | |||
34 | const head = document.getElementsByTagName('head')[0] | ||
35 | |||
36 | for (const theme of this.themes) { | ||
37 | |||
38 | for (const css of theme.css) { | ||
39 | const link = document.createElement('link') | ||
40 | |||
41 | const href = environment.apiUrl + `/themes/${theme.name}/${theme.version}/css/${css}` | ||
42 | link.setAttribute('href', href) | ||
43 | link.setAttribute('rel', 'alternate stylesheet') | ||
44 | link.setAttribute('type', 'text/css') | ||
45 | link.setAttribute('title', theme.name) | ||
46 | link.setAttribute('disabled', '') | ||
47 | |||
48 | head.appendChild(link) | ||
49 | } | ||
50 | } | ||
51 | } | ||
52 | |||
53 | private getCurrentTheme () { | ||
54 | if (this.auth.isLoggedIn()) { | ||
55 | const theme = this.auth.getUser().theme | ||
56 | if (theme !== 'instance-default') return theme | ||
57 | } | ||
58 | |||
59 | return this.server.getConfig().theme.default | ||
20 | } | 60 | } |
21 | 61 | ||
22 | toggleDarkTheme (setLocalStorage = true) { | 62 | private loadTheme (name: string) { |
23 | // switch properties | 63 | const links = document.getElementsByTagName('link') |
24 | this.switchProperty('mainBackgroundColor') | 64 | for (let i = 0; i < links.length; i++) { |
25 | this.switchProperty('mainForegroundColor') | 65 | const link = links[ i ] |
26 | this.switchProperty('submenuColor') | 66 | if (link.getAttribute('rel').indexOf('style') !== -1 && link.getAttribute('title')) { |
27 | this.switchProperty('inputColor') | 67 | link.disabled = link.getAttribute('title') !== name |
28 | this.switchProperty('inputPlaceholderColor') | 68 | } |
29 | 69 | } | |
30 | if (setLocalStorage) { | 70 | } |
31 | this.darkTheme = !this.darkTheme | 71 | |
32 | peertubeLocalStorage.setItem('theme', (this.darkTheme) ? 'dark' : 'default') | 72 | private updateCurrentTheme () { |
73 | if (this.oldThemeName) { | ||
74 | const oldTheme = this.getTheme(this.oldThemeName) | ||
75 | if (oldTheme) { | ||
76 | console.log('Removing scripts of old theme %s.', this.oldThemeName) | ||
77 | this.pluginService.removePlugin(oldTheme) | ||
78 | } | ||
79 | } | ||
80 | |||
81 | const currentTheme = this.getCurrentTheme() | ||
82 | |||
83 | console.log('Enabling %s theme.', currentTheme) | ||
84 | |||
85 | this.loadTheme(currentTheme) | ||
86 | const theme = this.getTheme(currentTheme) | ||
87 | if (theme) { | ||
88 | console.log('Adding scripts of theme %s.', currentTheme) | ||
89 | this.pluginService.addPlugin(theme) | ||
90 | |||
91 | this.pluginService.reloadLoadedScopes() | ||
33 | } | 92 | } |
93 | |||
94 | this.oldThemeName = currentTheme | ||
95 | } | ||
96 | |||
97 | private listenUserTheme () { | ||
98 | this.auth.userInformationLoaded | ||
99 | .subscribe(() => this.updateCurrentTheme()) | ||
34 | } | 100 | } |
35 | 101 | ||
36 | private switchProperty (property: string, newValue?: string) { | 102 | private getTheme (name: string) { |
37 | const propertyOldvalue = window.getComputedStyle(this.theme).getPropertyValue('--' + property) | 103 | return this.themes.find(t => t.name === name) |
38 | this.theme.style.setProperty('--' + property, (newValue) ? newValue : this.previousTheme[property]) | ||
39 | this.previousTheme[property] = propertyOldvalue | ||
40 | } | 104 | } |
41 | } | 105 | } |