@seniorsistemas/components-ai 0.0.0-master-d4a804fe
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +101 -0
- package/CONTRIBUTING.md +317 -0
- package/README.md +161 -0
- package/docs/API.md +486 -0
- package/docs/COMPONENTS.md +272 -0
- package/docs/EXAMPLES.md +559 -0
- package/docs/MIGRATION.md +367 -0
- package/esm2022/lib/angular-components.module.mjs +25 -0
- package/esm2022/lib/components/breadcrumb/breadcrumb.component.mjs +121 -0
- package/esm2022/lib/components/bulk-delete-dialog/bulk-delete-dialog.component.mjs +176 -0
- package/esm2022/lib/components/dynamic-form/dynamic-form.component.mjs +625 -0
- package/esm2022/lib/components/dynamic-form/fields/dynamic-field-date.component.mjs +86 -0
- package/esm2022/lib/components/dynamic-form/fields/dynamic-field-dropdown.component.mjs +103 -0
- package/esm2022/lib/components/dynamic-form/fields/dynamic-field-lookup.component.mjs +599 -0
- package/esm2022/lib/components/dynamic-form/fields/dynamic-field-number.component.mjs +92 -0
- package/esm2022/lib/components/dynamic-form/fields/dynamic-field-text.component.mjs +163 -0
- package/esm2022/lib/components/dynamic-form/fields/dynamic-field-textarea.component.mjs +81 -0
- package/esm2022/lib/components/dynamic-form/fields/dynamic-field-wrapper.component.mjs +93 -0
- package/esm2022/lib/components/dynamic-form/fields/index.mjs +8 -0
- package/esm2022/lib/components/dynamic-form/models/dynamic-form.models.mjs +2 -0
- package/esm2022/lib/components/export-dialog/export-dialog.component.mjs +219 -0
- package/esm2022/lib/config/translation.config.mjs +70 -0
- package/esm2022/lib/directives/cep-mask.directive.mjs +79 -0
- package/esm2022/lib/directives/document-mask.directive.mjs +62 -0
- package/esm2022/lib/directives/phone-mask.directive.mjs +59 -0
- package/esm2022/lib/interceptors/api.interceptor.mjs +55 -0
- package/esm2022/lib/models/base-entity.interface.mjs +2 -0
- package/esm2022/lib/models/entity-list.config.mjs +2 -0
- package/esm2022/lib/pipes/translate.pipe.mjs +74 -0
- package/esm2022/lib/services/auth.service.mjs +169 -0
- package/esm2022/lib/services/cookie.service.mjs +90 -0
- package/esm2022/lib/services/entity.service.mjs +208 -0
- package/esm2022/lib/services/mask.service.mjs +121 -0
- package/esm2022/lib/services/permission.service.mjs +180 -0
- package/esm2022/lib/services/senior-token.service.mjs +209 -0
- package/esm2022/lib/services/theme.service.mjs +85 -0
- package/esm2022/lib/services/translation.service.mjs +232 -0
- package/esm2022/public-api.mjs +90 -0
- package/esm2022/seniorsistemas-components-ai.mjs +5 -0
- package/fesm2022/seniorsistemas-components-ai.mjs +4006 -0
- package/fesm2022/seniorsistemas-components-ai.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/angular-components.module.d.ts +13 -0
- package/lib/components/breadcrumb/breadcrumb.component.d.ts +23 -0
- package/lib/components/bulk-delete-dialog/bulk-delete-dialog.component.d.ts +46 -0
- package/lib/components/dynamic-form/dynamic-form.component.d.ts +97 -0
- package/lib/components/dynamic-form/fields/dynamic-field-date.component.d.ts +16 -0
- package/lib/components/dynamic-form/fields/dynamic-field-dropdown.component.d.ts +17 -0
- package/lib/components/dynamic-form/fields/dynamic-field-lookup.component.d.ts +52 -0
- package/lib/components/dynamic-form/fields/dynamic-field-number.component.d.ts +16 -0
- package/lib/components/dynamic-form/fields/dynamic-field-text.component.d.ts +17 -0
- package/lib/components/dynamic-form/fields/dynamic-field-textarea.component.d.ts +16 -0
- package/lib/components/dynamic-form/fields/dynamic-field-wrapper.component.d.ts +20 -0
- package/lib/components/dynamic-form/fields/index.d.ts +7 -0
- package/lib/components/dynamic-form/models/dynamic-form.models.d.ts +178 -0
- package/lib/components/export-dialog/export-dialog.component.d.ts +56 -0
- package/lib/config/translation.config.d.ts +24 -0
- package/lib/directives/cep-mask.directive.d.ts +13 -0
- package/lib/directives/document-mask.directive.d.ts +19 -0
- package/lib/directives/phone-mask.directive.d.ts +11 -0
- package/lib/interceptors/api.interceptor.d.ts +2 -0
- package/lib/models/base-entity.interface.d.ts +7 -0
- package/lib/models/entity-list.config.d.ts +161 -0
- package/lib/pipes/translate.pipe.d.ts +21 -0
- package/lib/services/auth.service.d.ts +82 -0
- package/lib/services/cookie.service.d.ts +31 -0
- package/lib/services/entity.service.d.ts +99 -0
- package/lib/services/mask.service.d.ts +36 -0
- package/lib/services/permission.service.d.ts +91 -0
- package/lib/services/senior-token.service.d.ts +70 -0
- package/lib/services/theme.service.d.ts +16 -0
- package/lib/services/translation.service.d.ts +54 -0
- package/package.json +53 -0
- package/public-api.d.ts +17 -0
- package/src/lib/styles/entity-list.shared.scss +383 -0
- package/src/lib/styles/index.scss +10 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
import * as i1 from "./cookie.service";
|
|
4
|
+
/**
|
|
5
|
+
* Serviço para gerenciar o token Senior e extrair informações específicas
|
|
6
|
+
* para o sistema de traduções.
|
|
7
|
+
*
|
|
8
|
+
* Nota: Este serviço foca especificamente na extração do locale e informações
|
|
9
|
+
* básicas do usuário. Para funcionalidades completas de autenticação,
|
|
10
|
+
* use o AuthService que tem uma interface mais robusta.
|
|
11
|
+
*/
|
|
12
|
+
export class SeniorTokenService {
|
|
13
|
+
cookieService;
|
|
14
|
+
SENIOR_TOKEN_COOKIE = 'com.senior.token';
|
|
15
|
+
constructor(cookieService) {
|
|
16
|
+
this.cookieService = cookieService;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Obtém o token Senior completo do cookie
|
|
20
|
+
*/
|
|
21
|
+
getSeniorToken() {
|
|
22
|
+
// Tentar o nome padrão primeiro
|
|
23
|
+
let token = this.cookieService.getCookie(this.SENIOR_TOKEN_COOKIE);
|
|
24
|
+
if (!token) {
|
|
25
|
+
// Tentar nomes alternativos comuns
|
|
26
|
+
const alternativeNames = [
|
|
27
|
+
'com.senior.token',
|
|
28
|
+
'senior.token',
|
|
29
|
+
'senior_token',
|
|
30
|
+
'seniorToken',
|
|
31
|
+
'token',
|
|
32
|
+
'authToken',
|
|
33
|
+
'auth_token'
|
|
34
|
+
];
|
|
35
|
+
for (const name of alternativeNames) {
|
|
36
|
+
token = this.cookieService.getCookie(name);
|
|
37
|
+
if (token) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return token;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Decodifica e obtém os dados do token Senior
|
|
46
|
+
*/
|
|
47
|
+
getSeniorTokenData() {
|
|
48
|
+
const token = this.getSeniorToken();
|
|
49
|
+
if (!token) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
let tokenData;
|
|
54
|
+
// Primeiro, tentar como JSON direto (mais provável baseado na informação fornecida)
|
|
55
|
+
try {
|
|
56
|
+
tokenData = JSON.parse(token);
|
|
57
|
+
}
|
|
58
|
+
catch (jsonError) {
|
|
59
|
+
// Se falhar, tentar como JWT
|
|
60
|
+
if (token.includes('.')) {
|
|
61
|
+
const parts = token.split('.');
|
|
62
|
+
if (parts.length >= 2) {
|
|
63
|
+
const payload = parts[1];
|
|
64
|
+
// Adicionar padding se necessário
|
|
65
|
+
const paddedPayload = payload + '='.repeat((4 - payload.length % 4) % 4);
|
|
66
|
+
const decodedPayload = atob(paddedPayload);
|
|
67
|
+
tokenData = JSON.parse(decodedPayload);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
throw new Error('Invalid JWT format');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
throw jsonError; // Re-throw original JSON error
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return tokenData;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error('[SeniorTokenService] Error parsing Senior token:', error);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Obtém o locale do usuário do token Senior
|
|
86
|
+
*/
|
|
87
|
+
getUserLocale() {
|
|
88
|
+
const tokenData = this.getSeniorTokenData();
|
|
89
|
+
if (!tokenData) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
// O locale deve estar no mesmo nível do access_token
|
|
93
|
+
if (tokenData.locale) {
|
|
94
|
+
return tokenData.locale;
|
|
95
|
+
}
|
|
96
|
+
// Fallback: tentar outros campos comuns
|
|
97
|
+
const possibleLocaleFields = [
|
|
98
|
+
'language',
|
|
99
|
+
'lang',
|
|
100
|
+
'user_locale',
|
|
101
|
+
'userLocale',
|
|
102
|
+
'preferred_language',
|
|
103
|
+
'preferredLanguage'
|
|
104
|
+
];
|
|
105
|
+
for (const field of possibleLocaleFields) {
|
|
106
|
+
if (tokenData[field]) {
|
|
107
|
+
return tokenData[field];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Obtém informações do usuário do token Senior
|
|
114
|
+
*/
|
|
115
|
+
getUserInfo() {
|
|
116
|
+
const tokenData = this.getSeniorTokenData();
|
|
117
|
+
if (!tokenData) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
// Baseado na estrutura do AuthService, os campos devem estar no nível raiz
|
|
121
|
+
return {
|
|
122
|
+
userId: tokenData.userId || tokenData['sub'] || tokenData['user_id'] || tokenData.username,
|
|
123
|
+
userName: tokenData.userName || tokenData['name'] || tokenData['user_name'] || tokenData.username || tokenData.fullName,
|
|
124
|
+
locale: tokenData.locale,
|
|
125
|
+
email: tokenData.email,
|
|
126
|
+
fullName: tokenData.fullName
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Verifica se o usuário está logado (token existe e é válido)
|
|
131
|
+
*/
|
|
132
|
+
isUserLoggedIn() {
|
|
133
|
+
const tokenData = this.getSeniorTokenData();
|
|
134
|
+
if (!tokenData) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
// Verificar expiração se existir
|
|
138
|
+
if (tokenData['exp']) {
|
|
139
|
+
const now = Math.floor(Date.now() / 1000);
|
|
140
|
+
if (tokenData['exp'] < now) {
|
|
141
|
+
console.warn('Senior token has expired');
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Monitora mudanças no cookie do token (para detectar login/logout)
|
|
149
|
+
*/
|
|
150
|
+
watchTokenChanges(callback) {
|
|
151
|
+
let lastToken = this.getSeniorToken();
|
|
152
|
+
const checkToken = () => {
|
|
153
|
+
const currentToken = this.getSeniorToken();
|
|
154
|
+
if (currentToken !== lastToken) {
|
|
155
|
+
lastToken = currentToken;
|
|
156
|
+
const tokenData = this.getSeniorTokenData();
|
|
157
|
+
callback(tokenData);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
// Verificar a cada 5 segundos
|
|
161
|
+
setInterval(checkToken, 5000);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Valida se o token tem a estrutura esperada do Senior
|
|
165
|
+
*/
|
|
166
|
+
validateTokenStructure() {
|
|
167
|
+
const tokenData = this.getSeniorTokenData();
|
|
168
|
+
const issues = [];
|
|
169
|
+
if (!tokenData) {
|
|
170
|
+
issues.push('Token not found or could not be parsed');
|
|
171
|
+
return { isValid: false, issues };
|
|
172
|
+
}
|
|
173
|
+
// Verificar campos obrigatórios esperados
|
|
174
|
+
const requiredFields = ['access_token'];
|
|
175
|
+
const recommendedFields = ['locale', 'username', 'email'];
|
|
176
|
+
for (const field of requiredFields) {
|
|
177
|
+
if (!tokenData[field]) {
|
|
178
|
+
issues.push(`Missing required field: ${field}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
for (const field of recommendedFields) {
|
|
182
|
+
if (!tokenData[field]) {
|
|
183
|
+
issues.push(`Missing recommended field: ${field}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Verificar se locale está presente e é válido
|
|
187
|
+
if (tokenData.locale) {
|
|
188
|
+
// Importar a função de mapeamento seria circular, então fazer verificação básica
|
|
189
|
+
const supportedLocales = ['pt-BR', 'en-US', 'es-ES', 'pt', 'en', 'es'];
|
|
190
|
+
const locale = tokenData.locale;
|
|
191
|
+
const isSupported = supportedLocales.some(supportedLocale => locale.toLowerCase().includes(supportedLocale.toLowerCase()));
|
|
192
|
+
if (!isSupported) {
|
|
193
|
+
issues.push(`Locale '${locale}' might not be supported`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const isValid = issues.filter(issue => issue.includes('required')).length === 0;
|
|
197
|
+
console.log('[SeniorTokenService] Token validation result:', { isValid, issues });
|
|
198
|
+
return { isValid, issues };
|
|
199
|
+
}
|
|
200
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SeniorTokenService, deps: [{ token: i1.CookieService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
201
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SeniorTokenService, providedIn: 'root' });
|
|
202
|
+
}
|
|
203
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SeniorTokenService, decorators: [{
|
|
204
|
+
type: Injectable,
|
|
205
|
+
args: [{
|
|
206
|
+
providedIn: 'root'
|
|
207
|
+
}]
|
|
208
|
+
}], ctorParameters: () => [{ type: i1.CookieService }] });
|
|
209
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuaW9yLXRva2VuLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzLWFpL3NyYy9saWIvc2VydmljZXMvc2VuaW9yLXRva2VuLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7O0FBb0IzQzs7Ozs7OztHQU9HO0FBSUgsTUFBTSxPQUFPLGtCQUFrQjtJQUdUO0lBRkgsbUJBQW1CLEdBQUcsa0JBQWtCLENBQUM7SUFFMUQsWUFBb0IsYUFBNEI7UUFBNUIsa0JBQWEsR0FBYixhQUFhLENBQWU7SUFBRyxDQUFDO0lBRXBEOztPQUVHO0lBQ0gsY0FBYztRQUNaLGdDQUFnQztRQUNoQyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUVuRSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDWCxtQ0FBbUM7WUFDbkMsTUFBTSxnQkFBZ0IsR0FBRztnQkFDdkIsa0JBQWtCO2dCQUNsQixjQUFjO2dCQUNkLGNBQWM7Z0JBQ2QsYUFBYTtnQkFDYixPQUFPO2dCQUNQLFdBQVc7Z0JBQ1gsWUFBWTthQUNiLENBQUM7WUFFRixLQUFLLE1BQU0sSUFBSSxJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3BDLEtBQUssR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDM0MsSUFBSSxLQUFLLEVBQUUsQ0FBQztvQkFDVixNQUFNO2dCQUNSLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVEOztPQUVHO0lBQ0gsa0JBQWtCO1FBQ2hCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUVwQyxJQUFJLENB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QUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQ2hDLE1BQU0sV0FBVyxHQUFHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUMxRCxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUM3RCxDQUFDO1lBRUYsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNqQixNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsTUFBTSwwQkFBMEIsQ0FBQyxDQUFDO1lBQzNELENBQUM7UUFDSCxDQUFDO1FBRUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDO1FBRWhGLE9BQU8sQ0FBQyxHQUFHLENBQUMsK0NBQStDLEVBQUUsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUVsRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQzdCLENBQUM7d0dBM05VLGtCQUFrQjs0R0FBbEIsa0JBQWtCLGNBRmpCLE1BQU07OzRGQUVQLGtCQUFrQjtrQkFIOUIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb29raWVTZXJ2aWNlIH0gZnJvbSAnLi9jb29raWUuc2VydmljZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VuaW9yVG9rZW5EYXRhIHtcbiAgbG9jYWxlPzogc3RyaW5nO1xuICB1c2VySWQ/OiBzdHJpbmc7XG4gIHVzZXJOYW1lPzogc3RyaW5nO1xuICBhY2Nlc3NfdG9rZW4/OiBzdHJpbmc7XG4gIGV4cGlyZXNfaW4/OiBudW1iZXI7XG4gIHJlZnJlc2hfdG9rZW4/OiBzdHJpbmc7XG4gIHRva2VuX3R5cGU/OiBzdHJpbmc7XG4gIHJlZnJlc2hfZXhwaXJlc19pbj86IG51bWJlcjtcbiAgdXNlcm5hbWU/OiBzdHJpbmc7XG4gIGVtYWlsPzogc3RyaW5nO1xuICBmdWxsTmFtZT86IHN0cmluZztcbiAgdGVuYW50TmFtZT86IHN0cmluZztcbiAgdHlwZT86IHN0cmluZztcbiAgW2tleTogc3RyaW5nXTogYW55O1xufVxuXG4vKipcbiAqIFNlcnZpw6dvIHBhcmEgZ2VyZW5jaWFyIG8gdG9rZW4gU2VuaW9yIGUgZXh0cmFpciBpbmZvcm1hw6fDtWVzIGVzcGVjw61maWNhc1xuICogcGFyYSBvIHNpc3RlbWEgZGUgdHJhZHXDp8O1ZXMuXG4gKiBcbiAqIE5vdGE6IEVzdGUgc2VydmnDp28gZm9jYSBlc3BlY2lmaWNhbWVudGUgbmEgZXh0cmHDp8OjbyBkbyBsb2NhbGUgZSBpbmZvcm1hw6fDtWVzXG4gKiBiw6FzaWNhcyBkbyB1c3XDoXJpby4gUGFyYSBmdW5jaW9uYWxpZGFkZXMgY29tcGxldGFzIGRlIGF1dGVudGljYcOnw6NvLFxuICogdXNlIG8gQXV0aFNlcnZpY2UgcXVlIHRlbSB1bWEgaW50ZXJmYWNlIG1haXMgcm9idXN0YS5cbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgU2VuaW9yVG9rZW5TZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBTRU5JT1JfVE9LRU5fQ09PS0lFID0gJ2NvbS5zZW5pb3IudG9rZW4nO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY29va2llU2VydmljZTogQ29va2llU2VydmljZSkge31cblxuICAvKipcbiAgICogT2J0w6ltIG8gdG9rZW4gU2VuaW9yIGNvbXBsZXRvIGRvIGNvb2tpZVxuICAgKi9cbiAgZ2V0U2VuaW9yVG9rZW4oKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgLy8gVGVudGFyIG8gbm9tZSBwYWRyw6NvIHByaW1laXJvXG4gICAgbGV0IHRva2VuID0gdGhpcy5jb29raWVTZXJ2aWNlLmdldENvb2tpZSh0aGlzLlNFTklPUl9UT0tFTl9DT09LSUUpO1xuICAgIFxuICAgIGlmICghdG9rZW4pIHtcbiAgICAgIC8vIFRlbnRhciBub21lcyBhbHRlcm5hdGl2b3MgY29tdW5zXG4gICAgICBjb25zdCBhbHRlcm5hdGl2ZU5hbWVzID0gW1xuICAgICAgICAnY29tLnNlbmlvci50b2tlbicsXG4gICAgICAgICdzZW5pb3IudG9rZW4nLFxuICAgICAgICAnc2VuaW9yX3Rva2VuJyxcbiAgICAgICAgJ3NlbmlvclRva2VuJyxcbiAgICAgICAgJ3Rva2VuJyxcbiAgICAgICAgJ2F1dGhUb2tlbicsXG4gICAgICAgICdhdXRoX3Rva2VuJ1xuICAgICAgXTtcbiAgICAgIFxuICAgICAgZm9yIChjb25zdCBuYW1lIG9mIGFsdGVybmF0aXZlTmFtZXMpIHtcbiAgICAgICAgdG9rZW4gPSB0aGlzLmNvb2tpZVNlcnZpY2UuZ2V0Q29va2llKG5hbWUpO1xuICAgICAgICBpZiAodG9rZW4pIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICByZXR1cm4gdG9rZW47XG4gIH1cblxuICAvKipcbiAgICogRGVjb2RpZmljYSBlIG9idMOpbSBvcyBkYWRvcyBkbyB0b2tlbiBTZW5pb3JcbiAgICovXG4gIGdldFNlbmlvclRva2VuRGF0YSgpOiBTZW5pb3JUb2tlbkRhdGEgfCBudWxsIHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuZ2V0U2VuaW9yVG9rZW4oKTtcbiAgICBcbiAgICBpZiAoIXRva2VuKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgbGV0IHRva2VuRGF0YTogYW55O1xuICAgICAgXG4gICAgICAvLyBQcmltZWlybywgdGVudGFyIGNvbW8gSlNPTiBkaXJldG8gKG1haXMgcHJvdsOhdmVsIGJhc2VhZG8gbmEgaW5mb3JtYcOnw6NvIGZvcm5lY2lkYSlcbiAgICAgIHRyeSB7XG4gICAgICAgIHRva2VuRGF0YSA9IEpTT04ucGFyc2UodG9rZW4pO1xuICAgICAgfSBjYXRjaCAoanNvbkVycm9yKSB7XG4gICAgICAgIC8vIFNlIGZhbGhhciwgdGVudGFyIGNvbW8gSldUXG4gICAgICAgIGlmICh0b2tlbi5pbmNsdWRlcygnLicpKSB7XG4gICAgICAgICAgY29uc3QgcGFydHMgPSB0b2tlbi5zcGxpdCgnLicpO1xuICAgICAgICAgIGlmIChwYXJ0cy5sZW5ndGggPj0gMikge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHBhcnRzWzFdO1xuICAgICAgICAgICAgLy8gQWRpY2lvbmFyIHBhZGRpbmcgc2UgbmVjZXNzw6FyaW9cbiAgICAgICAgICAgIGNvbnN0IHBhZGRlZFBheWxvYWQgPSBwYXlsb2FkICsgJz0nLnJlcGVhdCgoNCAtIHBheWxvYWQubGVuZ3RoICUgNCkgJSA0KTtcbiAgICAgICAgICAgIGNvbnN0IGRlY29kZWRQYXlsb2FkID0gYXRvYihwYWRkZWRQYXlsb2FkKTtcbiAgICAgICAgICAgIHRva2VuRGF0YSA9IEpTT04ucGFyc2UoZGVjb2RlZFBheWxvYWQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgSldUIGZvcm1hdCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBqc29uRXJyb3I7IC8vIFJlLXRocm93IG9yaWdpbmFsIEpTT04gZXJyb3JcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdG9rZW5EYXRhIGFzIFNlbmlvclRva2VuRGF0YTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5lcnJvcignW1NlbmlvclRva2VuU2VydmljZV0gRXJyb3IgcGFyc2luZyBTZW5pb3IgdG9rZW46JywgZXJyb3IpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE9idMOpbSBvIGxvY2FsZSBkbyB1c3XDoXJpbyBkbyB0b2tlbiBTZW5pb3JcbiAgICovXG4gIGdldFVzZXJMb2NhbGUoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3QgdG9rZW5EYXRhID0gdGhpcy5nZXRTZW5pb3JUb2tlbkRhdGEoKTtcbiAgICBcbiAgICBpZiAoIXRva2VuRGF0YSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gTyBsb2NhbGUgZGV2ZSBlc3RhciBubyBtZXNtbyBuw612ZWwgZG8gYWNjZXNzX3Rva2VuXG4gICAgaWYgKHRva2VuRGF0YS5sb2NhbGUpIHtcbiAgICAgIHJldHVybiB0b2tlbkRhdGEubG9jYWxlO1xuICAgIH1cblxuICAgIC8vIEZhbGxiYWNrOiB0ZW50YXIgb3V0cm9zIGNhbXBvcyBjb211bnNcbiAgICBjb25zdCBwb3NzaWJsZUxvY2FsZUZpZWxkcyA9IFtcbiAgICAgICdsYW5ndWFnZScsIFxuICAgICAgJ2xhbmcnLFxuICAgICAgJ3VzZXJfbG9jYWxlJyxcbiAgICAgICd1c2VyTG9jYWxlJyxcbiAgICAgICdwcmVmZXJyZWRfbGFuZ3VhZ2UnLFxuICAgICAgJ3ByZWZlcnJlZExhbmd1YWdlJ1xuICAgIF07XG5cbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHBvc3NpYmxlTG9jYWxlRmllbGRzKSB7XG4gICAgICBpZiAodG9rZW5EYXRhW2ZpZWxkXSkge1xuICAgICAgICByZXR1cm4gdG9rZW5EYXRhW2ZpZWxkXTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogT2J0w6ltIGluZm9ybWHDp8O1ZXMgZG8gdXN1w6FyaW8gZG8gdG9rZW4gU2VuaW9yXG4gICAqL1xuICBnZXRVc2VySW5mbygpOiB7IHVzZXJJZD86IHN0cmluZzsgdXNlck5hbWU/OiBzdHJpbmc7IGxvY2FsZT86IHN0cmluZzsgZW1haWw/OiBzdHJpbmc7IGZ1bGxOYW1lPzogc3RyaW5nIH0gfCBudWxsIHtcbiAgICBjb25zdCB0b2tlbkRhdGEgPSB0aGlzLmdldFNlbmlvclRva2VuRGF0YSgpO1xuICAgIFxuICAgIGlmICghdG9rZW5EYXRhKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBCYXNlYWRvIG5hIGVzdHJ1dHVyYSBkbyBBdXRoU2VydmljZSwgb3MgY2FtcG9zIGRldmVtIGVzdGFyIG5vIG7DrXZlbCByYWl6XG4gICAgcmV0dXJuIHtcbiAgICAgIHVzZXJJZDogdG9rZW5EYXRhLnVzZXJJZCB8fCB0b2tlbkRhdGFbJ3N1YiddIHx8IHRva2VuRGF0YVsndXNlcl9pZCddIHx8IHRva2VuRGF0YS51c2VybmFtZSxcbiAgICAgIHVzZXJOYW1lOiB0b2tlbkRhdGEudXNlck5hbWUgfHwgdG9rZW5EYXRhWyduYW1lJ10gfHwgdG9rZW5EYXRhWyd1c2VyX25hbWUnXSB8fCB0b2tlbkRhdGEudXNlcm5hbWUgfHwgdG9rZW5EYXRhLmZ1bGxOYW1lLFxuICAgICAgbG9jYWxlOiB0b2tlbkRhdGEubG9jYWxlLFxuICAgICAgZW1haWw6IHRva2VuRGF0YS5lbWFpbCxcbiAgICAgIGZ1bGxOYW1lOiB0b2tlbkRhdGEuZnVsbE5hbWVcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWNhIHNlIG8gdXN1w6FyaW8gZXN0w6EgbG9nYWRvICh0b2tlbiBleGlzdGUgZSDDqSB2w6FsaWRvKVxuICAgKi9cbiAgaXNVc2VyTG9nZ2VkSW4oKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdG9rZW5EYXRhID0gdGhpcy5nZXRTZW5pb3JUb2tlbkRhdGEoKTtcbiAgICBcbiAgICBpZiAoIXRva2VuRGF0YSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIFZlcmlmaWNhciBleHBpcmHDp8OjbyBzZSBleGlzdGlyXG4gICAgaWYgKHRva2VuRGF0YVsnZXhwJ10pIHtcbiAgICAgIGNvbnN0IG5vdyA9IE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApO1xuICAgICAgaWYgKHRva2VuRGF0YVsnZXhwJ10gPCBub3cpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdTZW5pb3IgdG9rZW4gaGFzIGV4cGlyZWQnKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vbml0b3JhIG11ZGFuw6dhcyBubyBjb29raWUgZG8gdG9rZW4gKHBhcmEgZGV0ZWN0YXIgbG9naW4vbG9nb3V0KVxuICAgKi9cbiAgd2F0Y2hUb2tlbkNoYW5nZXMoY2FsbGJhY2s6ICh0b2tlbkRhdGE6IFNlbmlvclRva2VuRGF0YSB8IG51bGwpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBsZXQgbGFzdFRva2VuID0gdGhpcy5nZXRTZW5pb3JUb2tlbigpO1xuICAgIFxuICAgIGNvbnN0IGNoZWNrVG9rZW4gPSAoKSA9PiB7XG4gICAgICBjb25zdCBjdXJyZW50VG9rZW4gPSB0aGlzLmdldFNlbmlvclRva2VuKCk7XG4gICAgICBcbiAgICAgIGlmIChjdXJyZW50VG9rZW4gIT09IGxhc3RUb2tlbikge1xuICAgICAgICBsYXN0VG9rZW4gPSBjdXJyZW50VG9rZW47XG4gICAgICAgIGNvbnN0IHRva2VuRGF0YSA9IHRoaXMuZ2V0U2VuaW9yVG9rZW5EYXRhKCk7XG4gICAgICAgIGNhbGxiYWNrKHRva2VuRGF0YSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIC8vIFZlcmlmaWNhciBhIGNhZGEgNSBzZWd1bmRvc1xuICAgIHNldEludGVydmFsKGNoZWNrVG9rZW4sIDUwMDApO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYSBzZSBvIHRva2VuIHRlbSBhIGVzdHJ1dHVyYSBlc3BlcmFkYSBkbyBTZW5pb3JcbiAgICovXG4gIHZhbGlkYXRlVG9rZW5TdHJ1Y3R1cmUoKTogeyBpc1ZhbGlkOiBib29sZWFuOyBpc3N1ZXM6IHN0cmluZ1tdIH0ge1xuICAgIGNvbnN0IHRva2VuRGF0YSA9IHRoaXMuZ2V0U2VuaW9yVG9rZW5EYXRhKCk7XG4gICAgY29uc3QgaXNzdWVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIFxuICAgIGlmICghdG9rZW5EYXRhKSB7XG4gICAgICBpc3N1ZXMucHVzaCgnVG9rZW4gbm90IGZvdW5kIG9yIGNvdWxkIG5vdCBiZSBwYXJzZWQnKTtcbiAgICAgIHJldHVybiB7IGlzVmFsaWQ6IGZhbHNlLCBpc3N1ZXMgfTtcbiAgICB9XG4gICAgXG4gICAgLy8gVmVyaWZpY2FyIGNhbXBvcyBvYnJpZ2F0w7NyaW9zIGVzcGVyYWRvc1xuICAgIGNvbnN0IHJlcXVpcmVkRmllbGRzID0gWydhY2Nlc3NfdG9rZW4nXTtcbiAgICBjb25zdCByZWNvbW1lbmRlZEZpZWxkcyA9IFsnbG9jYWxlJywgJ3VzZXJuYW1lJywgJ2VtYWlsJ107XG4gICAgXG4gICAgZm9yIChjb25zdCBmaWVsZCBvZiByZXF1aXJlZEZpZWxkcykge1xuICAgICAgaWYgKCF0b2tlbkRhdGFbZmllbGRdKSB7XG4gICAgICAgIGlzc3Vlcy5wdXNoKGBNaXNzaW5nIHJlcXVpcmVkIGZpZWxkOiAke2ZpZWxkfWApO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHJlY29tbWVuZGVkRmllbGRzKSB7XG4gICAgICBpZiAoIXRva2VuRGF0YVtmaWVsZF0pIHtcbiAgICAgICAgaXNzdWVzLnB1c2goYE1pc3NpbmcgcmVjb21tZW5kZWQgZmllbGQ6ICR7ZmllbGR9YCk7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIC8vIFZlcmlmaWNhciBzZSBsb2NhbGUgZXN0w6EgcHJlc2VudGUgZSDDqSB2w6FsaWRvXG4gICAgaWYgKHRva2VuRGF0YS5sb2NhbGUpIHtcbiAgICAgIC8vIEltcG9ydGFyIGEgZnVuw6fDo28gZGUgbWFwZWFtZW50byBzZXJpYSBjaXJjdWxhciwgZW50w6NvIGZhemVyIHZlcmlmaWNhw6fDo28gYsOhc2ljYVxuICAgICAgY29uc3Qgc3VwcG9ydGVkTG9jYWxlcyA9IFsncHQtQlInLCAnZW4tVVMnLCAnZXMtRVMnLCAncHQnLCAnZW4nLCAnZXMnXTtcbiAgICAgIGNvbnN0IGxvY2FsZSA9IHRva2VuRGF0YS5sb2NhbGU7XG4gICAgICBjb25zdCBpc1N1cHBvcnRlZCA9IHN1cHBvcnRlZExvY2FsZXMuc29tZShzdXBwb3J0ZWRMb2NhbGUgPT4gXG4gICAgICAgIGxvY2FsZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHN1cHBvcnRlZExvY2FsZS50b0xvd2VyQ2FzZSgpKVxuICAgICAgKTtcbiAgICAgIFxuICAgICAgaWYgKCFpc1N1cHBvcnRlZCkge1xuICAgICAgICBpc3N1ZXMucHVzaChgTG9jYWxlICcke2xvY2FsZX0nIG1pZ2h0IG5vdCBiZSBzdXBwb3J0ZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgY29uc3QgaXNWYWxpZCA9IGlzc3Vlcy5maWx0ZXIoaXNzdWUgPT4gaXNzdWUuaW5jbHVkZXMoJ3JlcXVpcmVkJykpLmxlbmd0aCA9PT0gMDtcbiAgICBcbiAgICBjb25zb2xlLmxvZygnW1NlbmlvclRva2VuU2VydmljZV0gVG9rZW4gdmFsaWRhdGlvbiByZXN1bHQ6JywgeyBpc1ZhbGlkLCBpc3N1ZXMgfSk7XG4gICAgXG4gICAgcmV0dXJuIHsgaXNWYWxpZCwgaXNzdWVzIH07XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Injectable, Inject } from '@angular/core';
|
|
2
|
+
import { DOCUMENT } from '@angular/common';
|
|
3
|
+
import { BehaviorSubject } from 'rxjs';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export class ThemeService {
|
|
6
|
+
document;
|
|
7
|
+
isDarkModeSubject = new BehaviorSubject(false);
|
|
8
|
+
isDarkMode$ = this.isDarkModeSubject.asObservable();
|
|
9
|
+
mediaQuery;
|
|
10
|
+
constructor(document) {
|
|
11
|
+
this.document = document;
|
|
12
|
+
// Create media query to watch for system theme changes (kept for compatibility)
|
|
13
|
+
this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
14
|
+
// Check for saved theme preference, default to light theme
|
|
15
|
+
const savedTheme = localStorage.getItem('theme');
|
|
16
|
+
if (savedTheme === 'dark') {
|
|
17
|
+
// Only use dark theme if explicitly saved as dark
|
|
18
|
+
this.setTheme(true);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// Default to light theme, ignoring system preference
|
|
22
|
+
this.setTheme(false);
|
|
23
|
+
// Set default theme preference if not exists
|
|
24
|
+
if (!savedTheme) {
|
|
25
|
+
localStorage.setItem('theme', 'light');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
followSystemTheme() {
|
|
30
|
+
// This method is kept for compatibility but no longer used by default
|
|
31
|
+
// Set theme based on system preference only when explicitly requested
|
|
32
|
+
this.setTheme(this.mediaQuery.matches);
|
|
33
|
+
// Listen for system theme changes only when in auto mode
|
|
34
|
+
this.mediaQuery.addEventListener('change', (e) => {
|
|
35
|
+
const savedTheme = localStorage.getItem('theme');
|
|
36
|
+
if (savedTheme === 'auto') {
|
|
37
|
+
this.setTheme(e.matches);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
toggleTheme() {
|
|
42
|
+
const currentTheme = this.isDarkModeSubject.value;
|
|
43
|
+
this.setTheme(!currentTheme);
|
|
44
|
+
// When manually toggling, save the specific preference
|
|
45
|
+
localStorage.setItem('theme', !currentTheme ? 'dark' : 'light');
|
|
46
|
+
}
|
|
47
|
+
setThemeMode(mode) {
|
|
48
|
+
localStorage.setItem('theme', mode);
|
|
49
|
+
if (mode === 'auto') {
|
|
50
|
+
this.followSystemTheme();
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this.setTheme(mode === 'dark');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
setTheme(isDark) {
|
|
57
|
+
this.isDarkModeSubject.next(isDark);
|
|
58
|
+
// Apply theme to document
|
|
59
|
+
if (isDark) {
|
|
60
|
+
this.document.documentElement.classList.add('app-dark');
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.document.documentElement.classList.remove('app-dark');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
get isDarkMode() {
|
|
67
|
+
return this.isDarkModeSubject.value;
|
|
68
|
+
}
|
|
69
|
+
get currentThemeMode() {
|
|
70
|
+
const savedTheme = localStorage.getItem('theme');
|
|
71
|
+
return savedTheme || 'light'; // Default to light instead of auto
|
|
72
|
+
}
|
|
73
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
74
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, providedIn: 'root' });
|
|
75
|
+
}
|
|
76
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, decorators: [{
|
|
77
|
+
type: Injectable,
|
|
78
|
+
args: [{
|
|
79
|
+
providedIn: 'root'
|
|
80
|
+
}]
|
|
81
|
+
}], ctorParameters: () => [{ type: Document, decorators: [{
|
|
82
|
+
type: Inject,
|
|
83
|
+
args: [DOCUMENT]
|
|
84
|
+
}] }] });
|
|
85
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhlbWUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMtYWkvc3JjL2xpYi9zZXJ2aWNlcy90aGVtZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDOztBQUt2QyxNQUFNLE9BQU8sWUFBWTtJQUtlO0lBSjlCLGlCQUFpQixHQUFHLElBQUksZUFBZSxDQUFVLEtBQUssQ0FBQyxDQUFDO0lBQ3pELFdBQVcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDbkQsVUFBVSxDQUFpQjtJQUVuQyxZQUFzQyxRQUFrQjtRQUFsQixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ3RELGdGQUFnRjtRQUNoRixJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUVwRSwyREFBMkQ7UUFDM0QsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVqRCxJQUFJLFVBQVUsS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUMxQixrREFBa0Q7WUFDbEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QixDQUFDO2FBQU0sQ0FBQztZQUNOLHFEQUFxRDtZQUNyRCxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3JCLDZDQUE2QztZQUM3QyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ2hCLFlBQVksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ3pDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVPLGlCQUFpQjtRQUN2QixzRUFBc0U7UUFDdEUsc0VBQXNFO1FBQ3RFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUV2Qyx5REFBeUQ7UUFDekQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUMvQyxNQUFNLFVBQVUsR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2pELElBQUksVUFBVSxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUMxQixJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUMzQixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsV0FBVztRQUNULE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUM7UUFDbEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzdCLHVEQUF1RDtRQUN2RCxZQUFZLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBRUQsWUFBWSxDQUFDLElBQStCO1FBQzFDLFlBQVksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRXBDLElBQUksSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQzNCLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLENBQUM7UUFDakMsQ0FBQztJQUNILENBQUM7SUFFTyxRQUFRLENBQUMsTUFBZTtRQUM5QixJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXBDLDBCQUEwQjtRQUMxQixJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMxRCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDN0QsQ0FBQztJQUNILENBQUM7SUFFRCxJQUFJLFVBQVU7UUFDWixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUM7SUFDdEMsQ0FBQztJQUVELElBQUksZ0JBQWdCO1FBQ2xCLE1BQU0sVUFBVSxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakQsT0FBUSxVQUF3QyxJQUFJLE9BQU8sQ0FBQyxDQUFDLG1DQUFtQztJQUNsRyxDQUFDO3dHQTFFVSxZQUFZLGtCQUtILFFBQVE7NEdBTGpCLFlBQVksY0FGWCxNQUFNOzs0RkFFUCxZQUFZO2tCQUh4QixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQjs7MEJBTWMsTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgSW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgVGhlbWVTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBpc0RhcmtNb2RlU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuICBwdWJsaWMgaXNEYXJrTW9kZSQgPSB0aGlzLmlzRGFya01vZGVTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICBwcml2YXRlIG1lZGlhUXVlcnk6IE1lZGlhUXVlcnlMaXN0O1xuXG4gIGNvbnN0cnVjdG9yKEBJbmplY3QoRE9DVU1FTlQpIHByaXZhdGUgZG9jdW1lbnQ6IERvY3VtZW50KSB7XG4gICAgLy8gQ3JlYXRlIG1lZGlhIHF1ZXJ5IHRvIHdhdGNoIGZvciBzeXN0ZW0gdGhlbWUgY2hhbmdlcyAoa2VwdCBmb3IgY29tcGF0aWJpbGl0eSlcbiAgICB0aGlzLm1lZGlhUXVlcnkgPSB3aW5kb3cubWF0Y2hNZWRpYSgnKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKScpO1xuICAgIFxuICAgIC8vIENoZWNrIGZvciBzYXZlZCB0aGVtZSBwcmVmZXJlbmNlLCBkZWZhdWx0IHRvIGxpZ2h0IHRoZW1lXG4gICAgY29uc3Qgc2F2ZWRUaGVtZSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd0aGVtZScpO1xuICAgIFxuICAgIGlmIChzYXZlZFRoZW1lID09PSAnZGFyaycpIHtcbiAgICAgIC8vIE9ubHkgdXNlIGRhcmsgdGhlbWUgaWYgZXhwbGljaXRseSBzYXZlZCBhcyBkYXJrXG4gICAgICB0aGlzLnNldFRoZW1lKHRydWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBEZWZhdWx0IHRvIGxpZ2h0IHRoZW1lLCBpZ25vcmluZyBzeXN0ZW0gcHJlZmVyZW5jZVxuICAgICAgdGhpcy5zZXRUaGVtZShmYWxzZSk7XG4gICAgICAvLyBTZXQgZGVmYXVsdCB0aGVtZSBwcmVmZXJlbmNlIGlmIG5vdCBleGlzdHNcbiAgICAgIGlmICghc2F2ZWRUaGVtZSkge1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgndGhlbWUnLCAnbGlnaHQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZvbGxvd1N5c3RlbVRoZW1lKCk6IHZvaWQge1xuICAgIC8vIFRoaXMgbWV0aG9kIGlzIGtlcHQgZm9yIGNvbXBhdGliaWxpdHkgYnV0IG5vIGxvbmdlciB1c2VkIGJ5IGRlZmF1bHRcbiAgICAvLyBTZXQgdGhlbWUgYmFzZWQgb24gc3lzdGVtIHByZWZlcmVuY2Ugb25seSB3aGVuIGV4cGxpY2l0bHkgcmVxdWVzdGVkXG4gICAgdGhpcy5zZXRUaGVtZSh0aGlzLm1lZGlhUXVlcnkubWF0Y2hlcyk7XG4gICAgXG4gICAgLy8gTGlzdGVuIGZvciBzeXN0ZW0gdGhlbWUgY2hhbmdlcyBvbmx5IHdoZW4gaW4gYXV0byBtb2RlXG4gICAgdGhpcy5tZWRpYVF1ZXJ5LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIChlKSA9PiB7XG4gICAgICBjb25zdCBzYXZlZFRoZW1lID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3RoZW1lJyk7XG4gICAgICBpZiAoc2F2ZWRUaGVtZSA9PT0gJ2F1dG8nKSB7XG4gICAgICAgIHRoaXMuc2V0VGhlbWUoZS5tYXRjaGVzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHRvZ2dsZVRoZW1lKCk6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnRUaGVtZSA9IHRoaXMuaXNEYXJrTW9kZVN1YmplY3QudmFsdWU7XG4gICAgdGhpcy5zZXRUaGVtZSghY3VycmVudFRoZW1lKTtcbiAgICAvLyBXaGVuIG1hbnVhbGx5IHRvZ2dsaW5nLCBzYXZlIHRoZSBzcGVjaWZpYyBwcmVmZXJlbmNlXG4gICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ3RoZW1lJywgIWN1cnJlbnRUaGVtZSA/ICdkYXJrJyA6ICdsaWdodCcpO1xuICB9XG5cbiAgc2V0VGhlbWVNb2RlKG1vZGU6ICdsaWdodCcgfCAnZGFyaycgfCAnYXV0bycpOiB2b2lkIHtcbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgndGhlbWUnLCBtb2RlKTtcbiAgICBcbiAgICBpZiAobW9kZSA9PT0gJ2F1dG8nKSB7XG4gICAgICB0aGlzLmZvbGxvd1N5c3RlbVRoZW1lKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2V0VGhlbWUobW9kZSA9PT0gJ2RhcmsnKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNldFRoZW1lKGlzRGFyazogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaXNEYXJrTW9kZVN1YmplY3QubmV4dChpc0RhcmspO1xuICAgIFxuICAgIC8vIEFwcGx5IHRoZW1lIHRvIGRvY3VtZW50XG4gICAgaWYgKGlzRGFyaykge1xuICAgICAgdGhpcy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnYXBwLWRhcmsnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnYXBwLWRhcmsnKTtcbiAgICB9XG4gIH1cblxuICBnZXQgaXNEYXJrTW9kZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pc0RhcmtNb2RlU3ViamVjdC52YWx1ZTtcbiAgfVxuXG4gIGdldCBjdXJyZW50VGhlbWVNb2RlKCk6ICdsaWdodCcgfCAnZGFyaycgfCAnYXV0bycge1xuICAgIGNvbnN0IHNhdmVkVGhlbWUgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgndGhlbWUnKTtcbiAgICByZXR1cm4gKHNhdmVkVGhlbWUgYXMgJ2xpZ2h0JyB8ICdkYXJrJyB8ICdhdXRvJykgfHwgJ2xpZ2h0JzsgLy8gRGVmYXVsdCB0byBsaWdodCBpbnN0ZWFkIG9mIGF1dG9cbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { Injectable, Optional, Inject } from '@angular/core';
|
|
2
|
+
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
import { TRANSLATION_CONFIG, mapTokenLocaleToLanguage } from '../config/translation.config';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "./senior-token.service";
|
|
6
|
+
export class TranslationService {
|
|
7
|
+
seniorTokenService;
|
|
8
|
+
currentLanguage = new BehaviorSubject(TRANSLATION_CONFIG.defaultLanguage);
|
|
9
|
+
translations = {};
|
|
10
|
+
loadingLanguages = new Set();
|
|
11
|
+
translationLoader;
|
|
12
|
+
constructor(seniorTokenService, loader) {
|
|
13
|
+
this.seniorTokenService = seniorTokenService;
|
|
14
|
+
this.translationLoader = loader;
|
|
15
|
+
this.loadStoredLanguage();
|
|
16
|
+
// Carregar traduções do idioma inicial imediatamente
|
|
17
|
+
this.loadTranslations();
|
|
18
|
+
// Monitorar mudanças no token para atualizar idioma
|
|
19
|
+
this.watchTokenChanges();
|
|
20
|
+
}
|
|
21
|
+
get currentLanguage$() {
|
|
22
|
+
return this.currentLanguage.asObservable();
|
|
23
|
+
}
|
|
24
|
+
getCurrentLanguage() {
|
|
25
|
+
return this.currentLanguage.value;
|
|
26
|
+
}
|
|
27
|
+
async setLanguage(language) {
|
|
28
|
+
this.currentLanguage.next(language);
|
|
29
|
+
localStorage.setItem(TRANSLATION_CONFIG.storageKey, language);
|
|
30
|
+
await this.loadTranslations();
|
|
31
|
+
}
|
|
32
|
+
async waitForTranslations() {
|
|
33
|
+
const language = this.currentLanguage.value;
|
|
34
|
+
if (!this.isLanguageLoaded(language)) {
|
|
35
|
+
await this.loadTranslations();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Verifica se as traduções do idioma atual estão carregadas
|
|
40
|
+
*/
|
|
41
|
+
isLanguageLoaded(language) {
|
|
42
|
+
const lang = language || this.currentLanguage.value;
|
|
43
|
+
return !!this.translations[lang] && Object.keys(this.translations[lang]).length > 0;
|
|
44
|
+
}
|
|
45
|
+
translate(key, params) {
|
|
46
|
+
const currentLang = this.currentLanguage.value;
|
|
47
|
+
const translations = this.translations[currentLang];
|
|
48
|
+
if (!translations || Object.keys(translations).length === 0) {
|
|
49
|
+
// Se as traduções não estão carregadas, tentar carregar de forma assíncrona
|
|
50
|
+
if (!this.loadingLanguages.has(currentLang)) {
|
|
51
|
+
this.loadTranslations().catch(error => {
|
|
52
|
+
console.error('Error loading translations:', error);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
console.warn(`No translations loaded for language: ${currentLang}`);
|
|
56
|
+
return key;
|
|
57
|
+
}
|
|
58
|
+
// Para estrutura plana, buscar diretamente pela chave
|
|
59
|
+
const translation = translations[key];
|
|
60
|
+
if (!translation) {
|
|
61
|
+
console.warn(`Translation key not found: ${key}`);
|
|
62
|
+
return key;
|
|
63
|
+
}
|
|
64
|
+
if (typeof translation !== 'string') {
|
|
65
|
+
console.warn(`Translation key is not a string: ${key}`);
|
|
66
|
+
return key;
|
|
67
|
+
}
|
|
68
|
+
// Replace parameters if provided
|
|
69
|
+
if (params) {
|
|
70
|
+
return this.replaceParams(translation, params);
|
|
71
|
+
}
|
|
72
|
+
return translation;
|
|
73
|
+
}
|
|
74
|
+
async loadTranslations() {
|
|
75
|
+
const language = this.currentLanguage.value;
|
|
76
|
+
// Se já está carregado, não carregar novamente
|
|
77
|
+
if (this.isLanguageLoaded(language)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Evitar carregamentos duplicados
|
|
81
|
+
if (this.loadingLanguages.has(language)) {
|
|
82
|
+
// Aguardar um pouco e tentar novamente
|
|
83
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
84
|
+
if (this.isLanguageLoaded(language)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
this.loadingLanguages.add(language);
|
|
89
|
+
try {
|
|
90
|
+
await this.doLoadTranslations(language);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('Error in loadTranslations:', error);
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
this.loadingLanguages.delete(language);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async doLoadTranslations(language) {
|
|
100
|
+
try {
|
|
101
|
+
// Se há um loader customizado, usar ele
|
|
102
|
+
if (this.translationLoader) {
|
|
103
|
+
const translations = await this.translationLoader.loadTranslations(language);
|
|
104
|
+
this.translations[language] = translations;
|
|
105
|
+
console.log(`Translations loaded for ${language}:`, Object.keys(this.translations[language]).length, 'keys');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// Caso contrário, avisar que não há traduções
|
|
109
|
+
console.warn(`No translation loader provided. Translations for ${language} not loaded.`);
|
|
110
|
+
this.translations[language] = {};
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error(`Error loading translations for ${language}:`, error);
|
|
114
|
+
// Fallback para o idioma padrão se houver erro
|
|
115
|
+
if (language !== TRANSLATION_CONFIG.fallbackLanguage) {
|
|
116
|
+
try {
|
|
117
|
+
if (this.translationLoader) {
|
|
118
|
+
const fallbackTranslations = await this.translationLoader.loadTranslations(TRANSLATION_CONFIG.fallbackLanguage);
|
|
119
|
+
this.translations[language] = fallbackTranslations;
|
|
120
|
+
console.log(`Fallback translations loaded for ${language}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (fallbackError) {
|
|
124
|
+
console.error(`Error loading fallback translations:`, fallbackError);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
loadStoredLanguage() {
|
|
130
|
+
// 1. Primeiro, tentar obter do token Senior
|
|
131
|
+
const tokenLocale = this.seniorTokenService.getUserLocale();
|
|
132
|
+
if (tokenLocale) {
|
|
133
|
+
const mappedLanguage = mapTokenLocaleToLanguage(tokenLocale);
|
|
134
|
+
if (mappedLanguage) {
|
|
135
|
+
console.log(`Using language from Senior token: ${tokenLocale} -> ${mappedLanguage}`);
|
|
136
|
+
this.currentLanguage.next(mappedLanguage);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// 2. Segundo, tentar obter do localStorage
|
|
141
|
+
const stored = localStorage.getItem(TRANSLATION_CONFIG.storageKey);
|
|
142
|
+
const supportedCodes = TRANSLATION_CONFIG.supportedLanguages.map(lang => lang.code);
|
|
143
|
+
if (stored && supportedCodes.includes(stored)) {
|
|
144
|
+
console.log('Using language from localStorage:', stored);
|
|
145
|
+
this.currentLanguage.next(stored);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// 3. Por último, usar idioma padrão
|
|
149
|
+
console.log('Using default language:', TRANSLATION_CONFIG.defaultLanguage);
|
|
150
|
+
this.currentLanguage.next(TRANSLATION_CONFIG.defaultLanguage);
|
|
151
|
+
}
|
|
152
|
+
replaceParams(text, params) {
|
|
153
|
+
return text.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
154
|
+
return params[key] !== undefined ? params[key] : match;
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
getSupportedLanguages() {
|
|
158
|
+
return TRANSLATION_CONFIG.supportedLanguages;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Força o recarregamento das traduções (útil para desenvolvimento)
|
|
162
|
+
*/
|
|
163
|
+
async reloadTranslations() {
|
|
164
|
+
const language = this.currentLanguage.value;
|
|
165
|
+
delete this.translations[language];
|
|
166
|
+
await this.loadTranslations();
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Obtém todas as chaves de tradução carregadas
|
|
170
|
+
*/
|
|
171
|
+
getLoadedKeys() {
|
|
172
|
+
const language = this.currentLanguage.value;
|
|
173
|
+
const translations = this.translations[language];
|
|
174
|
+
return translations ? Object.keys(translations) : [];
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Verifica se um código de idioma é suportado
|
|
178
|
+
*/
|
|
179
|
+
isValidLanguage(locale) {
|
|
180
|
+
const supportedCodes = TRANSLATION_CONFIG.supportedLanguages.map(lang => lang.code);
|
|
181
|
+
return supportedCodes.includes(locale);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Monitora mudanças no token Senior para atualizar idioma automaticamente
|
|
185
|
+
*/
|
|
186
|
+
watchTokenChanges() {
|
|
187
|
+
this.seniorTokenService.watchTokenChanges((tokenData) => {
|
|
188
|
+
if (tokenData?.locale) {
|
|
189
|
+
const mappedLanguage = mapTokenLocaleToLanguage(tokenData.locale);
|
|
190
|
+
if (mappedLanguage) {
|
|
191
|
+
const newLocale = mappedLanguage;
|
|
192
|
+
const currentLocale = this.currentLanguage.value;
|
|
193
|
+
if (newLocale !== currentLocale) {
|
|
194
|
+
console.log(`Token locale changed: ${tokenData.locale} -> ${newLocale}`);
|
|
195
|
+
this.setLanguage(newLocale);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Força atualização do idioma baseado no token atual
|
|
203
|
+
*/
|
|
204
|
+
async syncWithToken() {
|
|
205
|
+
const tokenLocale = this.seniorTokenService.getUserLocale();
|
|
206
|
+
if (tokenLocale) {
|
|
207
|
+
const mappedLanguage = mapTokenLocaleToLanguage(tokenLocale);
|
|
208
|
+
if (mappedLanguage) {
|
|
209
|
+
const newLocale = mappedLanguage;
|
|
210
|
+
const currentLocale = this.currentLanguage.value;
|
|
211
|
+
if (newLocale !== currentLocale) {
|
|
212
|
+
console.log(`Syncing language with token: ${tokenLocale} -> ${newLocale}`);
|
|
213
|
+
await this.setLanguage(newLocale);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TranslationService, deps: [{ token: i1.SeniorTokenService }, { token: 'TranslationLoader', optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
219
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TranslationService, providedIn: 'root' });
|
|
220
|
+
}
|
|
221
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TranslationService, decorators: [{
|
|
222
|
+
type: Injectable,
|
|
223
|
+
args: [{
|
|
224
|
+
providedIn: 'root'
|
|
225
|
+
}]
|
|
226
|
+
}], ctorParameters: () => [{ type: i1.SeniorTokenService }, { type: undefined, decorators: [{
|
|
227
|
+
type: Optional
|
|
228
|
+
}, {
|
|
229
|
+
type: Inject,
|
|
230
|
+
args: ['TranslationLoader']
|
|
231
|
+
}] }] });
|
|
232
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMtYWkvc3JjL2xpYi9zZXJ2aWNlcy90cmFuc2xhdGlvbi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3RCxPQUFPLEVBQUUsZUFBZSxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxrQkFBa0IsRUFBa0Isd0JBQXdCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQzs7O0FBYTVHLE1BQU0sT0FBTyxrQkFBa0I7SUFTbkI7SUFSRixlQUFlLEdBQUcsSUFBSSxlQUFlLENBQzNDLGtCQUFrQixDQUFDLGVBQW9DLENBQ3hELENBQUM7SUFDTSxZQUFZLEdBQTJCLEVBQUUsQ0FBQztJQUMxQyxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO0lBQ3JDLGlCQUFpQixDQUFxQjtJQUU5QyxZQUNVLGtCQUFzQyxFQUNMLE1BQTBCO1FBRDNELHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBb0I7UUFHOUMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLE1BQU0sQ0FBQztRQUNoQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUMxQixxREFBcUQ7UUFDckQsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFFeEIsb0RBQW9EO1FBQ3BELElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCxJQUFJLGdCQUFnQjtRQUNsQixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDN0MsQ0FBQztJQUVELGtCQUFrQjtRQUNoQixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDO0lBQ3BDLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVyxD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RUFBRSxDQUFDO3dCQUNoQyxPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixTQUFTLENBQUMsTUFBTSxPQUFPLFNBQVMsRUFBRSxDQUFDLENBQUM7d0JBQ3pFLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7b0JBQzlCLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxhQUFhO1FBQ2pCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUM1RCxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLE1BQU0sY0FBYyxHQUFHLHdCQUF3QixDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQzdELElBQUksY0FBYyxFQUFFLENBQUM7Z0JBQ25CLE1BQU0sU0FBUyxHQUFHLGNBQW1DLENBQUM7Z0JBQ3RELE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDO2dCQUVqRCxJQUFJLFNBQVMsS0FBSyxhQUFhLEVBQUUsQ0FBQztvQkFDaEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQ0FBZ0MsV0FBVyxPQUFPLFNBQVMsRUFBRSxDQUFDLENBQUM7b0JBQzNFLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDcEMsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQzt3R0FuUFUsa0JBQWtCLG9EQVVQLG1CQUFtQjs0R0FWOUIsa0JBQWtCLGNBRmpCLE1BQU07OzRGQUVQLGtCQUFrQjtrQkFIOUIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkI7OzBCQVdJLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsbUJBQW1CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgT3B0aW9uYWwsIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBUUkFOU0xBVElPTl9DT05GSUcsIExhbmd1YWdlQ29uZmlnLCBtYXBUb2tlbkxvY2FsZVRvTGFuZ3VhZ2UgfSBmcm9tICcuLi9jb25maWcvdHJhbnNsYXRpb24uY29uZmlnJztcbmltcG9ydCB7IFNlbmlvclRva2VuU2VydmljZSB9IGZyb20gJy4vc2VuaW9yLXRva2VuLnNlcnZpY2UnO1xuXG5leHBvcnQgdHlwZSBTdXBwb3J0ZWRMYW5ndWFnZSA9ICdwdC1CUicgfCAnZW4tVVMnIHwgJ2VzLUVTJztcblxuLy8gSW50ZXJmYWNlIHBhcmEgbyBsb2FkZXIgZGUgdHJhZHXDp8O1ZXMgKGR1Y2sgdHlwaW5nKVxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2xhdGlvbkxvYWRlciB7XG4gIGxvYWRUcmFuc2xhdGlvbnMobGFuZ3VhZ2U6IHN0cmluZyk6IFByb21pc2U8YW55Pjtcbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgVHJhbnNsYXRpb25TZXJ2aWNlIHtcbiAgcHJpdmF0ZSBjdXJyZW50TGFuZ3VhZ2UgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFN1cHBvcnRlZExhbmd1YWdlPihcbiAgICBUUkFOU0xBVElPTl9DT05GSUcuZGVmYXVsdExhbmd1YWdlIGFzIFN1cHBvcnRlZExhbmd1YWdlXG4gICk7XG4gIHByaXZhdGUgdHJhbnNsYXRpb25zOiB7IFtrZXk6IHN0cmluZ106IGFueSB9ID0ge307XG4gIHByaXZhdGUgbG9hZGluZ0xhbmd1YWdlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBwcml2YXRlIHRyYW5zbGF0aW9uTG9hZGVyPzogVHJhbnNsYXRpb25Mb2FkZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBzZW5pb3JUb2tlblNlcnZpY2U6IFNlbmlvclRva2VuU2VydmljZSxcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KCdUcmFuc2xhdGlvbkxvYWRlcicpIGxvYWRlcj86IFRyYW5zbGF0aW9uTG9hZGVyXG4gICkge1xuICAgIHRoaXMudHJhbnNsYXRpb25Mb2FkZXIgPSBsb2FkZXI7XG4gICAgdGhpcy5sb2FkU3RvcmVkTGFuZ3VhZ2UoKTtcbiAgICAvLyBDYXJyZWdhciB0cmFkdcOnw7VlcyBkbyBpZGlvbWEgaW5pY2lhbCBpbWVkaWF0YW1lbnRlXG4gICAgdGhpcy5sb2FkVHJhbnNsYXRpb25zKCk7XG4gICAgXG4gICAgLy8gTW9uaXRvcmFyIG11ZGFuw6dhcyBubyB0b2tlbiBwYXJhIGF0dWFsaXphciBpZGlvbWFcbiAgICB0aGlzLndhdGNoVG9rZW5DaGFuZ2VzKCk7XG4gIH1cblxuICBnZXQgY3VycmVudExhbmd1YWdlJCgpOiBPYnNlcnZhYmxlPFN1cHBvcnRlZExhbmd1YWdlPiB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudExhbmd1YWdlLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgZ2V0Q3VycmVudExhbmd1YWdlKCk6IFN1cHBvcnRlZExhbmd1YWdlIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50TGFuZ3VhZ2UudmFsdWU7XG4gIH1cblxuICBhc3luYyBzZXRMYW5ndWFnZShsYW5ndWFnZTogU3VwcG9ydGVkTGFuZ3VhZ2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmN1cnJlbnRMYW5ndWFnZS5uZXh0KGxhbmd1YWdlKTtcbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShUUkFOU0xBVElPTl9DT05GSUcuc3RvcmFnZUtleSwgbGFuZ3VhZ2UpO1xuICAgIGF3YWl0IHRoaXMubG9hZFRyYW5zbGF0aW9ucygpO1xuICB9XG5cbiAgYXN5bmMgd2FpdEZvclRyYW5zbGF0aW9ucygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBsYW5ndWFnZSA9IHRoaXMuY3VycmVudExhbmd1YWdlLnZhbHVlO1xuICAgIGlmICghdGhpcy5pc0xhbmd1YWdlTG9hZGVkKGxhbmd1YWdlKSkge1xuICAgICAgYXdhaXQgdGhpcy5sb2FkVHJhbnNsYXRpb25zKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWNhIHNlIGFzIHRyYWR1w6fDtWVzIGRvIGlkaW9tYSBhdHVhbCBlc3TDo28gY2FycmVnYWRhc1xuICAgKi9cbiAgaXNMYW5ndWFnZUxvYWRlZChsYW5ndWFnZT86IFN1cHBvcnRlZExhbmd1YWdlKTogYm9vbGVhbiB7XG4gICAgY29uc3QgbGFuZyA9IGxhbmd1YWdlIHx8IHRoaXMuY3VycmVudExhbmd1YWdlLnZhbHVlO1xuICAgIHJldHVybiAhIXRoaXMudHJhbnNsYXRpb25zW2xhbmddICYmIE9iamVjdC5rZXlzKHRoaXMudHJhbnNsYXRpb25zW2xhbmddKS5sZW5ndGggPiAwO1xuICB9XG5cbiAgdHJhbnNsYXRlKGtleTogc3RyaW5nLCBwYXJhbXM/OiB7IFtrZXk6IHN0cmluZ106IGFueSB9KTogc3RyaW5nIHtcbiAgICBjb25zdCBjdXJyZW50TGFuZyA9IHRoaXMuY3VycmVudExhbmd1YWdlLnZhbHVlO1xuICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IHRoaXMudHJhbnNsYXRpb25zW2N1cnJlbnRMYW5nXTtcbiAgICBcbiAgICBpZiAoIXRyYW5zbGF0aW9ucyB8fCBPYmplY3Qua2V5cyh0cmFuc2xhdGlvbnMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgLy8gU2UgYXMgdHJhZHXDp8O1ZXMgbsOjbyBlc3TDo28gY2FycmVnYWRhcywgdGVudGFyIGNhcnJlZ2FyIGRlIGZvcm1hIGFzc8OtbmNyb25hXG4gICAgICBpZiAoIXRoaXMubG9hZGluZ0xhbmd1YWdlcy5oYXMoY3VycmVudExhbmcpKSB7XG4gICAgICAgIHRoaXMubG9hZFRyYW5zbGF0aW9ucygpLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBsb2FkaW5nIHRyYW5zbGF0aW9uczonLCBlcnJvcik7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgY29uc29sZS53YXJuKGBObyB0cmFuc2xhdGlvbnMgbG9hZGVkIGZvciBsYW5ndWFnZTogJHtjdXJyZW50TGFuZ31gKTtcbiAgICAgIHJldHVybiBrZXk7XG4gICAgfVxuXG4gICAgLy8gUGFyYSBlc3RydXR1cmEgcGxhbmEsIGJ1c2NhciBkaXJldGFtZW50ZSBwZWxhIGNoYXZlXG4gICAgY29uc3QgdHJhbnNsYXRpb24gPSB0cmFuc2xhdGlvbnNba2V5XTtcbiAgICBcbiAgICBpZiAoIXRyYW5zbGF0aW9uKSB7XG4gICAgICBjb25zb2xlLndhcm4oYFRyYW5zbGF0aW9uIGtleSBub3QgZm91bmQ6ICR7a2V5fWApO1xuICAgICAgcmV0dXJuIGtleTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHRyYW5zbGF0aW9uICE9PSAnc3RyaW5nJykge1xuICAgICAgY29uc29sZS53YXJuKGBUcmFuc2xhdGlvbiBrZXkgaXMgbm90IGEgc3RyaW5nOiAke2tleX1gKTtcbiAgICAgIHJldHVybiBrZXk7XG4gICAgfVxuXG4gICAgLy8gUmVwbGFjZSBwYXJhbWV0ZXJzIGlmIHByb3ZpZGVkXG4gICAgaWYgKHBhcmFtcykge1xuICAgICAgcmV0dXJuIHRoaXMucmVwbGFjZVBhcmFtcyh0cmFuc2xhdGlvbiwgcGFyYW1zKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJhbnNsYXRpb247XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvYWRUcmFuc2xhdGlvbnMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbGFuZ3VhZ2UgPSB0aGlzLmN1cnJlbnRMYW5ndWFnZS52YWx1ZTtcbiAgICBcbiAgICAvLyBTZSBqw6EgZXN0w6EgY2FycmVnYWRvLCBuw6NvIGNhcnJlZ2FyIG5vdmFtZW50ZVxuICAgIGlmICh0aGlzLmlzTGFuZ3VhZ2VMb2FkZWQobGFuZ3VhZ2UpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIFxuICAgIC8vIEV2aXRhciBjYXJyZWdhbWVudG9zIGR1cGxpY2Fkb3NcbiAgICBpZiAodGhpcy5sb2FkaW5nTGFuZ3VhZ2VzLmhhcyhsYW5ndWFnZSkpIHtcbiAgICAgIC8vIEFndWFyZGFyIHVtIHBvdWNvIGUgdGVudGFyIG5vdmFtZW50ZVxuICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMCkpO1xuICAgICAgaWYgKHRoaXMuaXNMYW5ndWFnZUxvYWRlZChsYW5ndWFnZSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICB0aGlzLmxvYWRpbmdMYW5ndWFnZXMuYWRkKGxhbmd1YWdlKTtcbiAgICBcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5kb0xvYWRUcmFuc2xhdGlvbnMobGFuZ3VhZ2UpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBpbiBsb2FkVHJhbnNsYXRpb25zOicsIGVycm9yKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5sb2FkaW5nTGFuZ3VhZ2VzLmRlbGV0ZShsYW5ndWFnZSk7XG4gICAgfVxuICB9XG4gIFxuICBwcml2YXRlIGFzeW5jIGRvTG9hZFRyYW5zbGF0aW9ucyhsYW5ndWFnZTogU3VwcG9ydGVkTGFuZ3VhZ2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgLy8gU2UgaMOhIHVtIGxvYWRlciBjdXN0b21pemFkbywgdXNhciBlbGVcbiAgICAgIGlmICh0aGlzLnRyYW5zbGF0aW9uTG9hZGVyKSB7XG4gICAgICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IGF3YWl0IHRoaXMudHJhbnNsYXRpb25Mb2FkZXIubG9hZFRyYW5zbGF0aW9ucyhsYW5ndWFnZSk7XG4gICAgICAgIHRoaXMudHJhbnNsYXRpb25zW2xhbmd1YWdlXSA9IHRyYW5zbGF0aW9ucztcbiAgICAgICAgY29uc29sZS5sb2coYFRyYW5zbGF0aW9ucyBsb2FkZWQgZm9yICR7bGFuZ3VhZ2V9OmAsIE9iamVjdC5rZXlzKHRoaXMudHJhbnNsYXRpb25zW2xhbmd1YWdlXSkubGVuZ3RoLCAna2V5cycpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIENhc28gY29udHLDoXJpbywgYXZpc2FyIHF1ZSBuw6NvIGjDoSB0cmFkdcOnw7Vlc1xuICAgICAgY29uc29sZS53YXJuKGBObyB0cmFuc2xhdGlvbiBsb2FkZXIgcHJvdmlkZWQuIFRyYW5zbGF0aW9ucyBmb3IgJHtsYW5ndWFnZX0gbm90IGxvYWRlZC5gKTtcbiAgICAgIHRoaXMudHJhbnNsYXRpb25zW2xhbmd1YWdlXSA9IHt9O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBsb2FkaW5nIHRyYW5zbGF0aW9ucyBmb3IgJHtsYW5ndWFnZX06YCwgZXJyb3IpO1xuICAgICAgLy8gRmFsbGJhY2sgcGFyYSBvIGlkaW9tYSBwYWRyw6NvIHNlIGhvdXZlciBlcnJvXG4gICAgICBpZiAobGFuZ3VhZ2UgIT09IFRSQU5TTEFUSU9OX0NPTkZJRy5mYWxsYmFja0xhbmd1YWdlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgaWYgKHRoaXMudHJhbnNsYXRpb25Mb2FkZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGZhbGxiYWNrVHJhbnNsYXRpb25zID0gYXdhaXQgdGhpcy50cmFuc2xhdGlvbkxvYWRlci5sb2FkVHJhbnNsYXRpb25zKFRSQU5TTEFUSU9OX0NPTkZJRy5mYWxsYmFja0xhbmd1YWdlKTtcbiAgICAgICAgICAgIHRoaXMudHJhbnNsYXRpb25zW2xhbmd1YWdlXSA9IGZhbGxiYWNrVHJhbnNsYXRpb25zO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYEZhbGxiYWNrIHRyYW5zbGF0aW9ucyBsb2FkZWQgZm9yICR7bGFuZ3VhZ2V9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChmYWxsYmFja0Vycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgbG9hZGluZyBmYWxsYmFjayB0cmFuc2xhdGlvbnM6YCwgZmFsbGJhY2tFcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGxvYWRTdG9yZWRMYW5ndWFnZSgpOiB2b2lkIHtcbiAgICAvLyAxLiBQcmltZWlybywgdGVudGFyIG9idGVyIGRvIHRva2VuIFNlbmlvclxuICAgIGNvbnN0IHRva2VuTG9jYWxlID0gdGhpcy5zZW5pb3JUb2tlblNlcnZpY2UuZ2V0VXNlckxvY2FsZSgpO1xuICAgIGlmICh0b2tlbkxvY2FsZSkge1xuICAgICAgY29uc3QgbWFwcGVkTGFuZ3VhZ2UgPSBtYXBUb2tlbkxvY2FsZVRvTGFuZ3VhZ2UodG9rZW5Mb2NhbGUpO1xuICAgICAgaWYgKG1hcHBlZExhbmd1YWdlKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBVc2luZyBsYW5ndWFnZSBmcm9tIFNlbmlvciB0b2tlbjogJHt0b2tlbkxvY2FsZX0gLT4gJHttYXBwZWRMYW5ndWFnZX1gKTtcbiAgICAgICAgdGhpcy5jdXJyZW50TGFuZ3VhZ2UubmV4dChtYXBwZWRMYW5ndWFnZSBhcyBTdXBwb3J0ZWRMYW5ndWFnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyAyLiBTZWd1bmRvLCB0ZW50YXIgb2J0ZXIgZG8gbG9jYWxTdG9yYWdlXG4gICAgY29uc3Qgc3RvcmVkID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oVFJBTlNMQVRJT05fQ09ORklHLnN0b3JhZ2VLZXkpIGFzIFN1cHBvcnRlZExhbmd1YWdlO1xuICAgIGNvbnN0IHN1cHBvcnRlZENvZGVzID0gVFJBTlNMQVRJT05fQ09ORklHLnN1cHBvcnRlZExhbmd1YWdlcy5tYXAobGFuZyA9PiBsYW5nLmNvZGUpO1xuICAgIGlmIChzdG9yZWQgJiYgc3VwcG9ydGVkQ29kZXMuaW5jbHVkZXMoc3RvcmVkKSkge1xuICAgICAgY29uc29sZS5sb2coJ1VzaW5nIGxhbmd1YWdlIGZyb20gbG9jYWxTdG9yYWdlOicsIHN0b3JlZCk7XG4gICAgICB0aGlzLmN1cnJlbnRMYW5ndWFnZS5uZXh0KHN0b3JlZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gMy4gUG9yIMO6bHRpbW8sIHVzYXIgaWRpb21hIHBhZHLDo29cbiAgICBjb25zb2xlLmxvZygnVXNpbmcgZGVmYXVsdCBsYW5ndWFnZTonLCBUUkFOU0xBVElPTl9DT05GSUcuZGVmYXVsdExhbmd1YWdlKTtcbiAgICB0aGlzLmN1cnJlbnRMYW5ndWFnZS5uZXh0KFRSQU5TTEFUSU9OX0NPTkZJRy5kZWZhdWx0TGFuZ3VhZ2UgYXMgU3VwcG9ydGVkTGFuZ3VhZ2UpO1xuICB9XG5cbiAgcHJpdmF0ZSByZXBsYWNlUGFyYW1zKHRleHQ6IHN0cmluZywgcGFyYW1zOiB7IFtrZXk6IHN0cmluZ106IGFueSB9KTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGV4dC5yZXBsYWNlKC9cXHtcXHsoXFx3KylcXH1cXH0vZywgKG1hdGNoLCBrZXkpID0+IHtcbiAgICAgIHJldHVybiBwYXJhbXNba2V5XSAhPT0gdW5kZWZpbmVkID8gcGFyYW1zW2tleV0gOiBtYXRjaDtcbiAgICB9KTtcbiAgfVxuXG4gIGdldFN1cHBvcnRlZExhbmd1YWdlcygpOiBMYW5ndWFnZUNvbmZpZ1tdIHtcbiAgICByZXR1cm4gVFJBTlNMQVRJT05fQ09ORklHLnN1cHBvcnRlZExhbmd1YWdlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3LDp2EgbyByZWNhcnJlZ2FtZW50byBkYXMgdHJhZHXDp8O1ZXMgKMO6dGlsIHBhcmEgZGVzZW52b2x2aW1lbnRvKVxuICAgKi9cbiAgYXN5bmMgcmVsb2FkVHJhbnNsYXRpb25zKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGxhbmd1YWdlID0gdGhpcy5jdXJyZW50TGFuZ3VhZ2UudmFsdWU7XG4gICAgZGVsZXRlIHRoaXMudHJhbnNsYXRpb25zW2xhbmd1YWdlXTtcbiAgICBhd2FpdCB0aGlzLmxvYWRUcmFuc2xhdGlvbnMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPYnTDqW0gdG9kYXMgYXMgY2hhdmVzIGRlIHRyYWR1w6fDo28gY2FycmVnYWRhc1xuICAgKi9cbiAgZ2V0TG9hZGVkS2V5cygpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgbGFuZ3VhZ2UgPSB0aGlzLmN1cnJlbnRMYW5ndWFnZS52YWx1ZTtcbiAgICBjb25zdCB0cmFuc2xhdGlvbnMgPSB0aGlzLnRyYW5zbGF0aW9uc1tsYW5ndWFnZV07XG4gICAgcmV0dXJuIHRyYW5zbGF0aW9ucyA/IE9iamVjdC5rZXlzKHRyYW5zbGF0aW9ucykgOiBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmljYSBzZSB1bSBjw7NkaWdvIGRlIGlkaW9tYSDDqSBzdXBvcnRhZG9cbiAgICovXG4gIHByaXZhdGUgaXNWYWxpZExhbmd1YWdlKGxvY2FsZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgc3VwcG9ydGVkQ29kZXMgPSBUUkFOU0xBVElPTl9DT05GSUcuc3VwcG9ydGVkTGFuZ3VhZ2VzLm1hcChsYW5nID0+IGxhbmcuY29kZSk7XG4gICAgcmV0dXJuIHN1cHBvcnRlZENvZGVzLmluY2x1ZGVzKGxvY2FsZSk7XG4gIH1cblxuICAvKipcbiAgICogTW9uaXRvcmEgbXVkYW7Dp2FzIG5vIHRva2VuIFNlbmlvciBwYXJhIGF0dWFsaXphciBpZGlvbWEgYXV0b21hdGljYW1lbnRlXG4gICAqL1xuICBwcml2YXRlIHdhdGNoVG9rZW5DaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMuc2VuaW9yVG9rZW5TZXJ2aWNlLndhdGNoVG9rZW5DaGFuZ2VzKCh0b2tlbkRhdGEpID0+IHtcbiAgICAgIGlmICh0b2tlbkRhdGE/LmxvY2FsZSkge1xuICAgICAgICBjb25zdCBtYXBwZWRMYW5ndWFnZSA9IG1hcFRva2VuTG9jYWxlVG9MYW5ndWFnZSh0b2tlbkRhdGEubG9jYWxlKTtcbiAgICAgICAgaWYgKG1hcHBlZExhbmd1YWdlKSB7XG4gICAgICAgICAgY29uc3QgbmV3TG9jYWxlID0gbWFwcGVkTGFuZ3VhZ2UgYXMgU3VwcG9ydGVkTGFuZ3VhZ2U7XG4gICAgICAgICAgY29uc3QgY3VycmVudExvY2FsZSA9IHRoaXMuY3VycmVudExhbmd1YWdlLnZhbHVlO1xuICAgICAgICAgIFxuICAgICAgICAgIGlmIChuZXdMb2NhbGUgIT09IGN1cnJlbnRMb2NhbGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBUb2tlbiBsb2NhbGUgY2hhbmdlZDogJHt0b2tlbkRhdGEubG9jYWxlfSAtPiAke25ld0xvY2FsZX1gKTtcbiAgICAgICAgICAgIHRoaXMuc2V0TGFuZ3VhZ2UobmV3TG9jYWxlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3LDp2EgYXR1YWxpemHDp8OjbyBkbyBpZGlvbWEgYmFzZWFkbyBubyB0b2tlbiBhdHVhbFxuICAgKi9cbiAgYXN5bmMgc3luY1dpdGhUb2tlbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0b2tlbkxvY2FsZSA9IHRoaXMuc2VuaW9yVG9rZW5TZXJ2aWNlLmdldFVzZXJMb2NhbGUoKTtcbiAgICBpZiAodG9rZW5Mb2NhbGUpIHtcbiAgICAgIGNvbnN0IG1hcHBlZExhbmd1YWdlID0gbWFwVG9rZW5Mb2NhbGVUb0xhbmd1YWdlKHRva2VuTG9jYWxlKTtcbiAgICAgIGlmIChtYXBwZWRMYW5ndWFnZSkge1xuICAgICAgICBjb25zdCBuZXdMb2NhbGUgPSBtYXBwZWRMYW5ndWFnZSBhcyBTdXBwb3J0ZWRMYW5ndWFnZTtcbiAgICAgICAgY29uc3QgY3VycmVudExvY2FsZSA9IHRoaXMuY3VycmVudExhbmd1YWdlLnZhbHVlO1xuICAgICAgICBcbiAgICAgICAgaWYgKG5ld0xvY2FsZSAhPT0gY3VycmVudExvY2FsZSkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGBTeW5jaW5nIGxhbmd1YWdlIHdpdGggdG9rZW46ICR7dG9rZW5Mb2NhbGV9IC0+ICR7bmV3TG9jYWxlfWApO1xuICAgICAgICAgIGF3YWl0IHRoaXMuc2V0TGFuZ3VhZ2UobmV3TG9jYWxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19
|