blob: 64c3f84589c97eea20a244b36910ccf994cbf851 [file] [log] [blame]
Adrià Vilanova Martínez2b50e912022-06-01 00:05:40 +02001import './add-language-dialog';
2
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +02003import {css, html, LitElement} from 'lit';
Adrià Vilanova Martínez2b50e912022-06-01 00:05:40 +02004import {customElement, property} from 'lit/decorators.js';
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +02005import {map} from 'lit/directives/map.js';
6
Adrià Vilanova Martínez5bdc4732022-05-31 20:12:21 +02007import {isoLangs} from '../../../common/consts';
8import {msg} from '../../../common/i18n';
Adrià Vilanova Martínez2b50e912022-06-01 00:05:40 +02009import {TargetLangs} from '../../../common/options';
Adrià Vilanova Martínez5bdc4732022-05-31 20:12:21 +020010import {SHARED_STYLES} from '../../shared/shared-styles';
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +020011
Adrià Vilanova Martínez2b50e912022-06-01 00:05:40 +020012@customElement('languages-editor')
13export default class LanguagesEditor extends LitElement {
14 @property({type: Object}) languages: TargetLangs;
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +020015
16 static get styles() {
17 return [
18 SHARED_STYLES,
19 css`
20 #languages_container {
21 width: 300px;
22 height: 250px;
23 border: 1px solid #ccc;
Adrià Vilanova Martínezb9180ef2022-05-29 20:26:43 +020024 background-color: #fafafa;
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +020025 overflow: auto;
26 }
27
28 #languages {
29 list-style: none;
30 margin: 0;
31 padding: 0;
32 }
33
34 #languages li {
35 display: flex;
36 flex-direction: row;
37 align-items: center;
38 padding: 15px;
39 border-bottom: 1px dashed #ddd;
Adrià Vilanova Martínezb9180ef2022-05-29 20:26:43 +020040 background-color: white;
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +020041 -webkit-user-select: none;
42 }
43
44 #languages li .label {
45 flex-grow: 1;
46 }
47
48 #languages li .delete {
49 font-size: 18px;
50 color: red;
51 padding-left: 2px;
52 margin-left: 2px;
53 }
54
55 #languages li .movebtn {
56 font-size: 16px;
57 color: blue;
58 padding: 0 2px;
59 margin: 0 2px;
60 }
61
62 #languages li :is(.delete, .movebtn) {
63 cursor: pointer;
64 text-align: center;
65 }
66
67 #languages li .movebtn--disabled {
68 color: gray;
69 cursor: not-allowed;
70 }
71
72 #languages_footer {
73 width: 300px;
74 height: 35px;
75 background-color: #fff;
76 border: 1px solid #ccc;
77 border-top: 0;
78 }
79
80 #languages_add {
81 margin-inline-start: 4px;
82 margin-top: 4px;
83 }
84 `,
85 ];
86 }
87
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +020088 render() {
Adrià Vilanova Martínez2b50e912022-06-01 00:05:40 +020089 const languageCodes = Object.values(this.languages ?? {});
90 const languageList = map(languageCodes, (lang, i) => {
91 const moveBtns = [];
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +020092 if (i != 0) {
93 moveBtns.push(html`
94 <button
95 class="notbtn movebtn"
96 @click=${() => this.swapLanguages(i, i - 1)}>
97
98 </button>
99 `);
100 } else {
101 moveBtns.push(html`
102 <button class="notbtn movebtn movebtn--disabled">
103
104 </button>
105 `);
106 }
107 if (i != languageCodes.length - 1) {
108 moveBtns.push(html`
109 <button
110 class="notbtn movebtn"
111 @click=${() => this.swapLanguages(i, i + 1)}>
112
113 </button>
114 `);
115 } else {
116 moveBtns.push(html`
117 <button class="notbtn movebtn movebtn--disabled">
118
119 </button>
120 `);
121 }
122
123 return html`
124 <li data-id=${lang}>
125 <span class="label">
126 ${isoLangs?.[lang]?.['name']} (${isoLangs?.[lang]?.nativeName})
127 </span>
128 ${moveBtns}
129 <button
130 class="notbtn delete"
131 @click=${() => this.deleteLanguage(lang)}>
132 ×
133 </button>
134 </li>
135 `;
136 });
137
138 return html`
139 <div id="languages_container">
140 <ul id="languages">${languageList}</ul>
141 </div>
142 <div id="languages_footer">
143 <button @click=${this.showAddLanguageDialog} id="languages_add">
144 ${msg('options_addlanguage_addbutton')}
145 </button>
146 </div>
147
148 <add-language-dialog .languages=${this.languages}></add-language-dialog>
149 `;
150 }
151
152 showAddLanguageDialog() {
153 const e = new CustomEvent(
154 'show-add-language-dialog', {bubbles: true, composed: true});
155 this.renderRoot.querySelector('add-language-dialog').dispatchEvent(e);
156 }
157
Adrià Vilanova Martínez2b50e912022-06-01 00:05:40 +0200158 save(languageCodes: string[]) {
159 const translateinto = Object.assign({}, languageCodes);
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +0200160 chrome.storage.sync.set({translateinto});
161 }
162
Adrià Vilanova Martínez2b50e912022-06-01 00:05:40 +0200163 deleteLanguage(deleteLang: string) {
164 const languageCodes =
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +0200165 Object.values(this.languages ?? {}).filter(lang => lang != deleteLang);
166 this.save(languageCodes);
167 }
168
Adrià Vilanova Martínez2b50e912022-06-01 00:05:40 +0200169 swapLanguages(i: number, j: number) {
170 const languageCodes = Object.values(this.languages ?? {});
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +0200171 if (i >= languageCodes.length || j >= languageCodes.length || i < 0 ||
172 j < 0) {
173 console.error(
174 'Can\'t swap languages because the indexes are out of the range.');
175 return;
176 }
Adrià Vilanova Martínez2b50e912022-06-01 00:05:40 +0200177 const tmp = languageCodes[j];
Adrià Vilanova Martíneze5263f12022-05-29 19:22:13 +0200178 languageCodes[j] = languageCodes[i];
179 languageCodes[i] = tmp;
180 this.save(languageCodes);
181 }
182}