tangled
alpha
login
or
join now
zzstoatzz.io
/
status
0
fork
atom
slack status without the slack
status.zzstoatzz.io/
quickslice
0
fork
atom
overview
issues
pulls
pipelines
Redesign emoji picker as immersive modal
zzstoatzz.io
5 months ago
e245682e
cfd09b95
+365
-100
1 changed file
expand all
collapse all
unified
split
templates
status.html
+365
-100
templates/status.html
···
190
190
</form>
191
191
</div>
192
192
193
193
-
<!-- Emoji Picker (hidden by default) -->
194
194
-
<div class="emoji-picker" id="emoji-picker" style="display: none;">
195
195
-
<div class="emoji-search-container">
196
196
-
<input type="text"
197
197
-
id="emoji-search"
198
198
-
class="emoji-search"
199
199
-
placeholder="Search emojis..."
200
200
-
autocomplete="off">
201
201
-
</div>
202
202
-
<div class="emoji-categories" id="emoji-categories">
203
203
-
<button class="category-btn active" data-category="frequent">Frequent</button>
204
204
-
<button class="category-btn" data-category="custom">Custom</button>
205
205
-
<button class="category-btn" data-category="people">People</button>
206
206
-
<button class="category-btn" data-category="nature">Nature</button>
207
207
-
<button class="category-btn" data-category="food">Food</button>
208
208
-
<button class="category-btn" data-category="activity">Activity</button>
209
209
-
<button class="category-btn" data-category="travel">Travel</button>
210
210
-
<button class="category-btn" data-category="objects">Objects</button>
211
211
-
<button class="category-btn" data-category="symbols">Symbols</button>
212
212
-
<button class="category-btn" data-category="flags">Flags</button>
213
213
-
</div>
214
214
-
<div class="emoji-grid" id="emoji-grid">
215
215
-
<!-- Will be populated by JavaScript -->
193
193
+
<!-- Emoji Picker Modal -->
194
194
+
<div class="emoji-picker-overlay hidden" id="emoji-picker-overlay" aria-hidden="true">
195
195
+
<div class="emoji-picker" id="emoji-picker" role="dialog" aria-modal="true" aria-labelledby="emoji-picker-title">
196
196
+
<div class="emoji-picker-header">
197
197
+
<div>
198
198
+
<h2 id="emoji-picker-title">pick an emoji</h2>
199
199
+
<p class="emoji-picker-subtitle">custom and unicode options side by side</p>
200
200
+
</div>
201
201
+
<button type="button" class="emoji-picker-close" id="emoji-picker-close" aria-label="close emoji picker">✕</button>
202
202
+
</div>
203
203
+
<div class="emoji-picker-preview">
204
204
+
<div class="emoji-preview-block">
205
205
+
<span class="emoji-preview-label">current</span>
206
206
+
<div class="emoji-preview-emoji" id="emoji-preview-current">
207
207
+
{% if let Some(current) = current_status.as_ref() %}
208
208
+
{% if current.status.starts_with("custom:") %}
209
209
+
{% let emoji_name = current.status.strip_prefix("custom:").unwrap() %}
210
210
+
<img src="/emojis/{{emoji_name}}.png" alt="{{emoji_name}}" title="{{emoji_name}}"
211
211
+
onerror="this.onerror=null; this.src='/emojis/{{emoji_name}}.gif';">
212
212
+
{% else %}
213
213
+
<span title="{{ current.status }}">{{ current.status }}</span>
214
214
+
{% endif %}
215
215
+
{% else %}
216
216
+
<span title="happy">😊</span>
217
217
+
{% endif %}
218
218
+
</div>
219
219
+
</div>
220
220
+
<div class="emoji-preview-block">
221
221
+
<span class="emoji-preview-label">next</span>
222
222
+
<div class="emoji-preview-emoji" id="emoji-preview-next">
223
223
+
{% if let Some(current) = current_status.as_ref() %}
224
224
+
{% if current.status.starts_with("custom:") %}
225
225
+
{% let emoji_name = current.status.strip_prefix("custom:").unwrap() %}
226
226
+
<img src="/emojis/{{emoji_name}}.png" alt="{{emoji_name}}" title="{{emoji_name}}"
227
227
+
onerror="this.onerror=null; this.src='/emojis/{{emoji_name}}.gif';">
228
228
+
{% else %}
229
229
+
<span title="{{ current.status }}">{{ current.status }}</span>
230
230
+
{% endif %}
231
231
+
{% else %}
232
232
+
<span title="happy">😊</span>
233
233
+
{% endif %}
234
234
+
</div>
235
235
+
</div>
236
236
+
</div>
237
237
+
<div class="emoji-search-container">
238
238
+
<input type="text"
239
239
+
id="emoji-search"
240
240
+
class="emoji-search"
241
241
+
placeholder="Search emojis..."
242
242
+
autocomplete="off">
243
243
+
</div>
244
244
+
<div class="emoji-picker-body">
245
245
+
<div class="emoji-categories" id="emoji-categories">
246
246
+
<button class="category-btn active" data-category="frequent">Frequent</button>
247
247
+
<button class="category-btn" data-category="custom">Custom</button>
248
248
+
<button class="category-btn" data-category="people">People</button>
249
249
+
<button class="category-btn" data-category="nature">Nature</button>
250
250
+
<button class="category-btn" data-category="food">Food</button>
251
251
+
<button class="category-btn" data-category="activity">Activity</button>
252
252
+
<button class="category-btn" data-category="travel">Travel</button>
253
253
+
<button class="category-btn" data-category="objects">Objects</button>
254
254
+
<button class="category-btn" data-category="symbols">Symbols</button>
255
255
+
<button class="category-btn" data-category="flags">Flags</button>
256
256
+
</div>
257
257
+
<div class="emoji-grid" id="emoji-grid">
258
258
+
<!-- Will be populated by JavaScript -->
259
259
+
</div>
260
260
+
</div>
216
261
</div>
217
262
</div>
218
263
···
455
500
<style>
456
501
body {
457
502
font-family: var(--font-family) !important;
503
503
+
}
504
504
+
505
505
+
body.modal-open {
506
506
+
overflow: hidden;
458
507
}
459
508
460
509
:root {
···
1049
1098
}
1050
1099
1051
1100
/* Emoji Picker */
1101
1101
+
.emoji-picker-overlay {
1102
1102
+
position: fixed;
1103
1103
+
inset: 0;
1104
1104
+
background: rgba(6, 6, 8, 0.75);
1105
1105
+
backdrop-filter: blur(6px);
1106
1106
+
display: flex;
1107
1107
+
align-items: center;
1108
1108
+
justify-content: center;
1109
1109
+
padding: clamp(1rem, 6vw, 2.5rem);
1110
1110
+
z-index: 1400;
1111
1111
+
}
1112
1112
+
1113
1113
+
.emoji-picker-overlay.hidden {
1114
1114
+
display: none;
1115
1115
+
}
1116
1116
+
1052
1117
.emoji-picker {
1053
1053
-
position: absolute;
1118
1118
+
width: min(720px, 100%);
1119
1119
+
max-height: min(90vh, 720px);
1054
1120
background: var(--bg-secondary);
1055
1121
border: 1px solid var(--border-color);
1122
1122
+
border-radius: clamp(var(--radius), 2vw, 24px);
1123
1123
+
box-shadow: 0 32px 80px rgba(0, 0, 0, 0.45);
1124
1124
+
display: flex;
1125
1125
+
flex-direction: column;
1126
1126
+
gap: 1rem;
1127
1127
+
padding: clamp(1.25rem, 5vw, 2rem);
1128
1128
+
overflow: hidden;
1129
1129
+
}
1130
1130
+
1131
1131
+
.emoji-picker-header {
1132
1132
+
display: flex;
1133
1133
+
align-items: flex-start;
1134
1134
+
justify-content: space-between;
1135
1135
+
gap: 1rem;
1136
1136
+
}
1137
1137
+
1138
1138
+
.emoji-picker-header h2 {
1139
1139
+
margin: 0;
1140
1140
+
font-size: 1.5rem;
1141
1141
+
color: var(--text-primary);
1142
1142
+
}
1143
1143
+
1144
1144
+
.emoji-picker-subtitle {
1145
1145
+
margin: 0.25rem 0 0;
1146
1146
+
font-size: 0.875rem;
1147
1147
+
color: var(--text-tertiary);
1148
1148
+
}
1149
1149
+
1150
1150
+
.emoji-picker-close {
1151
1151
+
border: 1px solid var(--border-color);
1152
1152
+
background: var(--bg-tertiary);
1153
1153
+
color: var(--text-secondary);
1154
1154
+
border-radius: 999px;
1155
1155
+
width: 2.25rem;
1156
1156
+
height: 2.25rem;
1157
1157
+
display: flex;
1158
1158
+
align-items: center;
1159
1159
+
justify-content: center;
1160
1160
+
cursor: pointer;
1161
1161
+
transition: all 0.2s ease;
1162
1162
+
}
1163
1163
+
1164
1164
+
.emoji-picker-close:hover,
1165
1165
+
.emoji-picker-close:focus-visible {
1166
1166
+
color: white;
1167
1167
+
background: var(--accent);
1168
1168
+
border-color: transparent;
1169
1169
+
outline: none;
1170
1170
+
}
1171
1171
+
1172
1172
+
.emoji-picker-preview {
1173
1173
+
display: flex;
1174
1174
+
gap: 1rem;
1175
1175
+
background: var(--bg-primary);
1056
1176
border-radius: var(--radius);
1177
1177
+
border: 1px solid var(--border-color);
1057
1178
padding: 1rem;
1058
1058
-
box-shadow: var(--shadow-md);
1059
1059
-
width: 320px;
1060
1060
-
max-height: 400px;
1061
1061
-
overflow-y: auto;
1062
1062
-
z-index: 1000;
1179
1179
+
}
1180
1180
+
1181
1181
+
.emoji-preview-block {
1182
1182
+
flex: 1;
1183
1183
+
display: flex;
1184
1184
+
flex-direction: column;
1185
1185
+
align-items: center;
1186
1186
+
gap: 0.5rem;
1187
1187
+
}
1188
1188
+
1189
1189
+
.emoji-preview-label {
1190
1190
+
font-size: 0.75rem;
1191
1191
+
text-transform: uppercase;
1192
1192
+
letter-spacing: 0.08em;
1193
1193
+
color: var(--text-tertiary);
1194
1194
+
}
1195
1195
+
1196
1196
+
.emoji-preview-emoji {
1197
1197
+
width: clamp(3.25rem, 16vw, 4.5rem);
1198
1198
+
height: clamp(3.25rem, 16vw, 4.5rem);
1199
1199
+
display: flex;
1200
1200
+
align-items: center;
1201
1201
+
justify-content: center;
1202
1202
+
font-size: clamp(2rem, 10vw, 3rem);
1203
1203
+
border-radius: var(--radius);
1204
1204
+
background: var(--bg-secondary);
1205
1205
+
border: 1px solid rgba(255, 255, 255, 0.05);
1206
1206
+
overflow: hidden;
1207
1207
+
}
1208
1208
+
1209
1209
+
.emoji-preview-emoji img {
1210
1210
+
width: 100%;
1211
1211
+
height: 100%;
1212
1212
+
object-fit: contain;
1213
1213
+
}
1214
1214
+
1215
1215
+
.emoji-preview-emoji span {
1216
1216
+
display: block;
1063
1217
}
1064
1218
1065
1219
.emoji-search-container {
1066
1066
-
margin-bottom: 1rem;
1220
1220
+
margin: 0;
1067
1221
}
1068
1222
1069
1223
.emoji-search {
1070
1224
width: 100%;
1071
1071
-
padding: 0.5rem 0.75rem;
1225
1225
+
padding: 0.75rem 1rem;
1072
1226
background: var(--bg-primary);
1073
1227
border: 1px solid var(--border-color);
1074
1074
-
border-radius: var(--radius-sm);
1228
1228
+
border-radius: var(--radius);
1075
1229
color: var(--text-primary);
1076
1076
-
font-size: 0.875rem;
1230
1230
+
font-size: 0.95rem;
1077
1231
outline: none;
1078
1078
-
transition: border-color 0.2s;
1232
1232
+
transition: border-color 0.2s ease, box-shadow 0.2s ease;
1079
1233
}
1080
1234
1081
1235
.emoji-search:focus {
1082
1236
border-color: var(--accent);
1083
1083
-
box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.1);
1237
1237
+
box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.12);
1084
1238
}
1085
1239
1086
1240
.emoji-search::placeholder {
1087
1241
color: var(--text-tertiary);
1088
1242
}
1089
1243
1244
1244
+
.emoji-picker-body {
1245
1245
+
flex: 1;
1246
1246
+
display: flex;
1247
1247
+
flex-direction: column;
1248
1248
+
gap: 0.75rem;
1249
1249
+
min-height: 0;
1250
1250
+
}
1251
1251
+
1090
1252
.emoji-categories {
1091
1253
display: flex;
1092
1092
-
gap: 0.25rem;
1093
1093
-
margin-bottom: 1rem;
1254
1254
+
gap: 0.5rem;
1094
1255
overflow-x: auto;
1095
1256
padding-bottom: 0.5rem;
1257
1257
+
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
1096
1258
}
1097
1259
1098
1260
.emoji-categories.hidden {
···
1101
1263
1102
1264
.category-btn {
1103
1265
background: transparent;
1104
1104
-
border: none;
1266
1266
+
border: 1px solid transparent;
1105
1267
color: var(--text-secondary);
1106
1106
-
font-size: 0.75rem;
1107
1107
-
padding: 0.25rem 0.5rem;
1268
1268
+
font-size: 0.8rem;
1269
1269
+
padding: 0.4rem 0.75rem;
1108
1270
cursor: pointer;
1109
1271
white-space: nowrap;
1110
1110
-
border-radius: var(--radius-sm);
1111
1111
-
transition: all 0.2s;
1272
1272
+
border-radius: 999px;
1273
1273
+
transition: all 0.2s ease;
1112
1274
}
1113
1275
1114
1114
-
.category-btn:hover {
1115
1115
-
background: var(--bg-tertiary);
1276
1276
+
.category-btn:hover,
1277
1277
+
.category-btn:focus-visible {
1278
1278
+
border-color: var(--accent);
1279
1279
+
color: var(--accent);
1280
1280
+
outline: none;
1116
1281
}
1117
1282
1118
1283
.category-btn.active {
1119
1284
background: var(--accent);
1120
1285
color: white;
1286
1286
+
border-color: transparent;
1121
1287
}
1122
1288
1123
1289
.emoji-grid {
1290
1290
+
flex: 1;
1124
1291
display: grid;
1125
1125
-
grid-template-columns: repeat(auto-fill, 2rem);
1126
1126
-
gap: 0.25rem;
1127
1127
-
justify-content: start;
1292
1292
+
grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
1293
1293
+
gap: 0.5rem;
1294
1294
+
padding-right: 0.25rem;
1295
1295
+
overflow-y: auto;
1128
1296
}
1129
1297
1130
1298
.emoji-option {
1131
1131
-
background: transparent;
1132
1132
-
border: none;
1133
1133
-
font-size: 1.5rem;
1134
1134
-
padding: 0.25rem;
1299
1299
+
background: var(--bg-primary);
1300
1300
+
border: 1px solid transparent;
1301
1301
+
font-size: 2rem;
1135
1302
cursor: pointer;
1136
1136
-
border-radius: var(--radius-sm);
1137
1137
-
transition: background 0.2s;
1303
1303
+
border-radius: 16px;
1304
1304
+
transition: transform 0.15s ease, border-color 0.2s ease, background 0.2s ease;
1138
1305
display: flex;
1139
1306
align-items: center;
1140
1307
justify-content: center;
1141
1141
-
width: 2rem;
1142
1142
-
height: 2rem;
1308
1308
+
width: 100%;
1309
1309
+
aspect-ratio: 1;
1310
1310
+
position: relative;
1143
1311
}
1144
1312
1145
1145
-
.emoji-option:hover {
1313
1313
+
.emoji-option:hover,
1314
1314
+
.emoji-option:focus-visible {
1146
1315
background: var(--bg-tertiary);
1316
1316
+
border-color: var(--accent);
1317
1317
+
transform: translateY(-2px);
1318
1318
+
outline: none;
1147
1319
}
1148
1320
1149
1149
-
/* Custom emoji styles */
1150
1150
-
.emoji-option.custom-emoji {
1151
1151
-
padding: 0.125rem;
1321
1321
+
.emoji-option.custom-emoji img {
1322
1322
+
width: 70%;
1323
1323
+
height: 70%;
1324
1324
+
object-fit: contain;
1152
1325
}
1153
1326
1154
1154
-
.emoji-option.custom-emoji img {
1155
1155
-
width: 1.75rem;
1156
1156
-
height: 1.75rem;
1157
1157
-
object-fit: contain;
1327
1327
+
.emoji-option.custom-emoji::after {
1328
1328
+
content: '';
1329
1329
+
position: absolute;
1330
1330
+
inset: 8%;
1331
1331
+
border-radius: 12px;
1332
1332
+
pointer-events: none;
1333
1333
+
}
1334
1334
+
1335
1335
+
@media (max-width: 640px) {
1336
1336
+
.emoji-picker-overlay {
1337
1337
+
padding: 0;
1338
1338
+
align-items: stretch;
1339
1339
+
}
1340
1340
+
1341
1341
+
.emoji-picker {
1342
1342
+
width: 100%;
1343
1343
+
height: 100%;
1344
1344
+
max-height: none;
1345
1345
+
border-radius: 0;
1346
1346
+
padding: 1.25rem 1rem 1rem;
1347
1347
+
gap: 0.75rem;
1348
1348
+
}
1349
1349
+
1350
1350
+
.emoji-picker-preview {
1351
1351
+
padding: 0.75rem;
1352
1352
+
}
1353
1353
+
1354
1354
+
.emoji-grid {
1355
1355
+
grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
1356
1356
+
}
1158
1357
}
1159
1358
1160
1359
/* Clear Picker */
···
1937
2136
1938
2137
// Emoji picker
1939
2138
const emojiTrigger = document.getElementById('emoji-trigger');
2139
2139
+
const emojiPickerOverlay = document.getElementById('emoji-picker-overlay');
1940
2140
const emojiPicker = document.getElementById('emoji-picker');
2141
2141
+
const emojiPickerClose = document.getElementById('emoji-picker-close');
1941
2142
const emojiGrid = document.getElementById('emoji-grid');
1942
2143
const selectedEmoji = document.getElementById('selected-emoji');
1943
2144
const statusInput = document.getElementById('status-input');
2145
2145
+
const emojiPreviewCurrent = document.getElementById('emoji-preview-current');
2146
2146
+
const emojiPreviewNext = document.getElementById('emoji-preview-next');
2147
2147
+
let lastFocusBeforeEmojiPicker = null;
1944
2148
1945
2149
// Clear time picker
1946
2150
const clearAfterBtn = document.getElementById('clear-after-btn');
···
1948
2152
const clearText = document.getElementById('clear-text');
1949
2153
const expiresSelect = document.getElementById('expires_in');
1950
2154
2155
2155
+
const isEmojiPickerOpen = () => emojiPickerOverlay && !emojiPickerOverlay.classList.contains('hidden');
2156
2156
+
2157
2157
+
const syncPreviewWithSelection = () => {
2158
2158
+
if (emojiPreviewNext && selectedEmoji) {
2159
2159
+
emojiPreviewNext.innerHTML = selectedEmoji.innerHTML;
2160
2160
+
}
2161
2161
+
};
2162
2162
+
2163
2163
+
syncPreviewWithSelection();
2164
2164
+
2165
2165
+
const openEmojiPicker = () => {
2166
2166
+
if (!emojiPickerOverlay || !emojiPicker) return;
2167
2167
+
2168
2168
+
lastFocusBeforeEmojiPicker = document.activeElement;
2169
2169
+
2170
2170
+
emojiPickerOverlay.classList.remove('hidden');
2171
2171
+
emojiPickerOverlay.setAttribute('aria-hidden', 'false');
2172
2172
+
document.body.classList.add('modal-open');
2173
2173
+
if (clearPicker) clearPicker.style.display = 'none';
2174
2174
+
2175
2175
+
const emojiSearch = document.getElementById('emoji-search');
2176
2176
+
if (emojiSearch) {
2177
2177
+
emojiSearch.value = '';
2178
2178
+
const categories = document.getElementById('emoji-categories');
2179
2179
+
if (categories) categories.classList.remove('hidden');
2180
2180
+
setTimeout(() => {
2181
2181
+
if (emojiSearch) emojiSearch.focus();
2182
2182
+
}, 60);
2183
2183
+
}
2184
2184
+
2185
2185
+
if (emojiPreviewCurrent) {
2186
2186
+
const currentDisplay = document.querySelector('.current-status .status-emoji');
2187
2187
+
if (currentDisplay) {
2188
2188
+
emojiPreviewCurrent.innerHTML = currentDisplay.innerHTML;
2189
2189
+
} else if (selectedEmoji) {
2190
2190
+
emojiPreviewCurrent.innerHTML = selectedEmoji.innerHTML;
2191
2191
+
}
2192
2192
+
}
2193
2193
+
2194
2194
+
syncPreviewWithSelection();
2195
2195
+
2196
2196
+
loadCustomEmojis().then(() => {
2197
2197
+
loadEmojiCategory('frequent');
2198
2198
+
});
2199
2199
+
};
2200
2200
+
2201
2201
+
const closeEmojiPicker = () => {
2202
2202
+
if (!emojiPickerOverlay) return;
2203
2203
+
emojiPickerOverlay.classList.add('hidden');
2204
2204
+
emojiPickerOverlay.setAttribute('aria-hidden', 'true');
2205
2205
+
document.body.classList.remove('modal-open');
2206
2206
+
if (lastFocusBeforeEmojiPicker && typeof lastFocusBeforeEmojiPicker.focus === 'function') {
2207
2207
+
const focusTarget = lastFocusBeforeEmojiPicker;
2208
2208
+
setTimeout(() => {
2209
2209
+
try { focusTarget.focus(); } catch (_) {}
2210
2210
+
}, 50);
2211
2211
+
}
2212
2212
+
lastFocusBeforeEmojiPicker = null;
2213
2213
+
};
2214
2214
+
1951
2215
// Show emoji picker
1952
1952
-
if (emojiTrigger && emojiPicker) {
2216
2216
+
if (emojiTrigger && emojiPickerOverlay) {
1953
2217
emojiTrigger.addEventListener('click', (e) => {
2218
2218
+
e.preventDefault();
1954
2219
e.stopPropagation();
1955
1955
-
const wasHidden = emojiPicker.style.display === 'none';
1956
1956
-
emojiPicker.style.display = wasHidden ? 'block' : 'none';
1957
1957
-
clearPicker.style.display = 'none';
1958
1958
-
1959
1959
-
if (wasHidden) {
1960
1960
-
// Position picker
1961
1961
-
const rect = emojiTrigger.getBoundingClientRect();
1962
1962
-
emojiPicker.style.top = rect.bottom + 'px';
1963
1963
-
emojiPicker.style.left = rect.left + 'px';
1964
1964
-
1965
1965
-
// Clear search and show categories
1966
1966
-
const emojiSearch = document.getElementById('emoji-search');
1967
1967
-
if (emojiSearch) {
1968
1968
-
emojiSearch.value = '';
1969
1969
-
document.getElementById('emoji-categories').classList.remove('hidden');
1970
1970
-
}
1971
1971
-
1972
1972
-
// Load frequent emojis by default (wait for custom emojis to be loaded first)
1973
1973
-
loadCustomEmojis().then(() => {
1974
1974
-
loadEmojiCategory('frequent');
1975
1975
-
});
1976
1976
-
1977
1977
-
// Focus search for easy typing
1978
1978
-
setTimeout(() => {
1979
1979
-
if (emojiSearch) emojiSearch.focus();
1980
1980
-
}, 50);
2220
2220
+
if (isEmojiPickerOpen()) {
2221
2221
+
closeEmojiPicker();
2222
2222
+
} else {
2223
2223
+
openEmojiPicker();
1981
2224
}
1982
2225
});
1983
2226
}
2227
2227
+
2228
2228
+
if (emojiPickerClose) {
2229
2229
+
emojiPickerClose.addEventListener('click', (e) => {
2230
2230
+
e.preventDefault();
2231
2231
+
closeEmojiPicker();
2232
2232
+
});
2233
2233
+
}
2234
2234
+
2235
2235
+
if (emojiPickerOverlay) {
2236
2236
+
emojiPickerOverlay.addEventListener('click', (e) => {
2237
2237
+
if (e.target === emojiPickerOverlay) {
2238
2238
+
closeEmojiPicker();
2239
2239
+
}
2240
2240
+
});
2241
2241
+
}
2242
2242
+
2243
2243
+
document.addEventListener('keydown', (e) => {
2244
2244
+
if (e.key === 'Escape' && isEmojiPickerOpen()) {
2245
2245
+
closeEmojiPicker();
2246
2246
+
}
2247
2247
+
});
1984
2248
1985
2249
// Store custom emojis
1986
2250
let customEmojis = [];
···
2003
2267
document.addEventListener('custom-emoji-uploaded', async (e) => {
2004
2268
await loadCustomEmojis();
2005
2269
// If picker visible, refresh current category
2006
2006
-
if (emojiPicker && emojiPicker.style.display !== 'none') {
2270
2270
+
if (isEmojiPickerOpen()) {
2007
2271
const active = document.querySelector('.emoji-categories .category-btn.active');
2008
2272
const cat = active ? active.getAttribute('data-category') : 'frequent';
2009
2273
loadEmojiCategory(cat || 'frequent');
···
2050
2314
}
2051
2315
2052
2316
statusInput.value = emoji;
2053
2053
-
emojiPicker.style.display = 'none';
2317
2317
+
syncPreviewWithSelection();
2318
2318
+
closeEmojiPicker();
2054
2319
checkForChanges();
2055
2320
});
2056
2321
});
···
2077
2342
// Display the image in the selected emoji area
2078
2343
selectedEmoji.innerHTML = `<img src="${img.src}" alt="${img.alt}" style="width: 100%; height: 100%; object-fit: contain;">`;
2079
2344
statusInput.value = emojiValue;
2080
2080
-
emojiPicker.style.display = 'none';
2345
2345
+
syncPreviewWithSelection();
2346
2346
+
closeEmojiPicker();
2081
2347
checkForChanges();
2082
2348
});
2083
2349
});
···
2095
2361
const emoji = e.target.getAttribute('data-emoji');
2096
2362
selectedEmoji.textContent = emoji;
2097
2363
statusInput.value = emoji;
2098
2098
-
emojiPicker.style.display = 'none';
2364
2364
+
syncPreviewWithSelection();
2365
2365
+
closeEmojiPicker();
2099
2366
checkForChanges();
2100
2367
});
2101
2368
});
···
2119
2386
clearAfterBtn.addEventListener('click', (e) => {
2120
2387
e.stopPropagation();
2121
2388
clearPicker.style.display = clearPicker.style.display === 'none' ? 'block' : 'none';
2122
2122
-
emojiPicker.style.display = 'none';
2389
2389
+
closeEmojiPicker();
2123
2390
2124
2391
// Position picker
2125
2392
const rect = clearAfterBtn.getBoundingClientRect();
···
2228
2495
2229
2496
// Close pickers on outside click
2230
2497
document.addEventListener('click', (e) => {
2231
2231
-
if (!emojiPicker.contains(e.target) && e.target !== emojiTrigger) {
2232
2232
-
emojiPicker.style.display = 'none';
2233
2233
-
}
2234
2234
-
if (!clearPicker.contains(e.target) && e.target !== clearAfterBtn) {
2498
2498
+
if (clearPicker && !clearPicker.contains(e.target) && e.target !== clearAfterBtn) {
2235
2499
clearPicker.style.display = 'none';
2236
2500
}
2237
2501
});
···
2331
2595
}
2332
2596
2333
2597
statusInput.value = emojiValue;
2334
2334
-
emojiPicker.style.display = 'none';
2598
2598
+
syncPreviewWithSelection();
2599
2599
+
closeEmojiPicker();
2335
2600
checkForChanges();
2336
2601
// Clear search when emoji is selected
2337
2602
document.getElementById('emoji-search').value = '';