+25
-141
templates/status.html
+25
-141
templates/status.html
···
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
-
<div class="emoji-picker-preview">
204
-
<div class="emoji-preview-block">
205
-
<span class="emoji-preview-label">current</span>
206
-
<div class="emoji-preview-emoji" id="emoji-preview-current">
207
-
{% if let Some(current) = current_status.as_ref() %}
208
-
{% if current.status.starts_with("custom:") %}
209
-
{% let emoji_name = current.status.strip_prefix("custom:").unwrap() %}
210
-
<img src="/emojis/{{emoji_name}}.png" alt="{{emoji_name}}" title="{{emoji_name}}"
211
-
onerror="this.onerror=null; this.src='/emojis/{{emoji_name}}.gif';">
212
-
{% else %}
213
-
<span title="{{ current.status }}">{{ current.status }}</span>
214
-
{% endif %}
215
-
{% else %}
216
-
<span title="happy">๐</span>
217
-
{% endif %}
218
-
</div>
219
-
</div>
220
-
<div class="emoji-preview-block">
221
-
<span class="emoji-preview-label">next</span>
222
-
<div class="emoji-preview-emoji" id="emoji-preview-next">
223
-
{% if let Some(current) = current_status.as_ref() %}
224
-
{% if current.status.starts_with("custom:") %}
225
-
{% let emoji_name = current.status.strip_prefix("custom:").unwrap() %}
226
-
<img src="/emojis/{{emoji_name}}.png" alt="{{emoji_name}}" title="{{emoji_name}}"
227
-
onerror="this.onerror=null; this.src='/emojis/{{emoji_name}}.gif';">
228
-
{% else %}
229
-
<span title="{{ current.status }}">{{ current.status }}</span>
230
-
{% endif %}
231
-
{% else %}
232
-
<span title="happy">๐</span>
233
-
{% endif %}
234
-
</div>
235
-
</div>
236
-
</div>
237
203
<div class="emoji-search-container">
238
204
<input type="text"
239
205
id="emoji-search"
···
1115
1081
}
1116
1082
1117
1083
.emoji-picker {
1118
-
width: min(720px, 100%);
1119
-
max-height: min(90vh, 720px);
1084
+
width: min(960px, 94vw);
1085
+
height: min(90vh, 820px);
1120
1086
background: var(--bg-secondary);
1121
1087
border: 1px solid var(--border-color);
1122
1088
border-radius: clamp(var(--radius), 2vw, 24px);
1123
1089
box-shadow: 0 32px 80px rgba(0, 0, 0, 0.45);
1124
1090
display: flex;
1125
1091
flex-direction: column;
1126
-
gap: 1rem;
1127
-
padding: clamp(1.25rem, 5vw, 2rem);
1092
+
gap: 1.25rem;
1093
+
padding: clamp(1.25rem, 5vw, 2.5rem);
1128
1094
overflow: hidden;
1129
1095
}
1096
+
1130
1097
1131
1098
.emoji-picker-header {
1132
1099
display: flex;
···
1169
1136
outline: none;
1170
1137
}
1171
1138
1172
-
.emoji-picker-preview {
1173
-
display: flex;
1174
-
gap: 1rem;
1175
-
background: var(--bg-primary);
1176
-
border-radius: var(--radius);
1177
-
border: 1px solid var(--border-color);
1178
-
padding: 1rem;
1179
-
}
1180
-
1181
-
.emoji-preview-block {
1182
-
flex: 1;
1183
-
display: flex;
1184
-
flex-direction: column;
1185
-
align-items: center;
1186
-
gap: 0.5rem;
1187
-
}
1188
-
1189
-
.emoji-preview-label {
1190
-
font-size: 0.75rem;
1191
-
text-transform: uppercase;
1192
-
letter-spacing: 0.08em;
1193
-
color: var(--text-tertiary);
1194
-
}
1195
-
1196
-
.emoji-preview-emoji {
1197
-
width: clamp(3.25rem, 16vw, 4.5rem);
1198
-
height: clamp(3.25rem, 16vw, 4.5rem);
1199
-
display: flex;
1200
-
align-items: center;
1201
-
justify-content: center;
1202
-
font-size: clamp(2rem, 10vw, 3rem);
1203
-
border-radius: var(--radius);
1204
-
background: var(--bg-secondary);
1205
-
border: 1px solid rgba(255, 255, 255, 0.05);
1206
-
overflow: hidden;
1207
-
}
1208
-
1209
-
.emoji-preview-emoji img {
1210
-
width: 100%;
1211
-
height: 100%;
1212
-
object-fit: contain;
1213
-
}
1214
-
1215
-
.emoji-preview-emoji span {
1216
-
display: block;
1217
-
}
1218
-
1219
1139
.emoji-search-container {
1220
1140
margin: 0;
1221
1141
}
···
1251
1171
1252
1172
.emoji-categories {
1253
1173
display: flex;
1254
-
gap: 0.5rem;
1174
+
gap: 0.75rem;
1255
1175
overflow-x: auto;
1256
1176
padding-bottom: 0.5rem;
1257
1177
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
···
1289
1209
.emoji-grid {
1290
1210
flex: 1;
1291
1211
display: grid;
1292
-
grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
1293
-
gap: 0.5rem;
1212
+
grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
1213
+
gap: 0.75rem;
1294
1214
padding-right: 0.25rem;
1295
1215
overflow-y: auto;
1296
1216
}
1297
1217
1298
1218
.emoji-option {
1299
-
background: var(--bg-primary);
1300
-
border: 1px solid transparent;
1301
-
font-size: 2rem;
1219
+
background: transparent;
1220
+
border: none;
1221
+
font-size: 2.4rem;
1302
1222
cursor: pointer;
1303
-
border-radius: 16px;
1304
-
transition: transform 0.15s ease, border-color 0.2s ease, background 0.2s ease;
1223
+
transition: transform 0.15s ease;
1305
1224
display: flex;
1306
1225
align-items: center;
1307
1226
justify-content: center;
1308
1227
width: 100%;
1309
1228
aspect-ratio: 1;
1310
-
position: relative;
1229
+
}
1230
+
1231
+
.emoji-option:hover {
1232
+
transform: translateY(-3px) scale(1.05);
1311
1233
}
1312
1234
1313
-
.emoji-option:hover,
1314
1235
.emoji-option:focus-visible {
1315
-
background: var(--bg-tertiary);
1316
-
border-color: var(--accent);
1317
-
transform: translateY(-2px);
1318
-
outline: none;
1236
+
outline: 2px solid var(--accent);
1237
+
outline-offset: 6px;
1238
+
border-radius: 16px;
1319
1239
}
1320
1240
1321
1241
.emoji-option.custom-emoji img {
1322
-
width: 70%;
1323
-
height: 70%;
1242
+
width: 75%;
1243
+
height: 75%;
1324
1244
object-fit: contain;
1325
1245
}
1326
1246
1327
-
.emoji-option.custom-emoji::after {
1328
-
content: '';
1329
-
position: absolute;
1330
-
inset: 8%;
1331
-
border-radius: 12px;
1332
-
pointer-events: none;
1333
-
}
1334
-
1335
1247
@media (max-width: 640px) {
1336
1248
.emoji-picker-overlay {
1337
1249
padding: 0;
···
1343
1255
height: 100%;
1344
1256
max-height: none;
1345
1257
border-radius: 0;
1346
-
padding: 1.25rem 1rem 1rem;
1347
-
gap: 0.75rem;
1348
-
}
1349
-
1350
-
.emoji-picker-preview {
1351
-
padding: 0.75rem;
1258
+
padding: 1.5rem 1rem;
1259
+
gap: 1rem;
1352
1260
}
1353
1261
1354
1262
.emoji-grid {
1355
-
grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
1263
+
grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
1264
+
gap: 0.5rem;
1356
1265
}
1357
1266
}
1358
1267
···
2142
2051
const emojiGrid = document.getElementById('emoji-grid');
2143
2052
const selectedEmoji = document.getElementById('selected-emoji');
2144
2053
const statusInput = document.getElementById('status-input');
2145
-
const emojiPreviewCurrent = document.getElementById('emoji-preview-current');
2146
-
const emojiPreviewNext = document.getElementById('emoji-preview-next');
2147
2054
let lastFocusBeforeEmojiPicker = null;
2148
2055
2149
2056
// Clear time picker
···
2153
2060
const expiresSelect = document.getElementById('expires_in');
2154
2061
2155
2062
const isEmojiPickerOpen = () => emojiPickerOverlay && !emojiPickerOverlay.classList.contains('hidden');
2156
-
2157
-
const syncPreviewWithSelection = () => {
2158
-
if (emojiPreviewNext && selectedEmoji) {
2159
-
emojiPreviewNext.innerHTML = selectedEmoji.innerHTML;
2160
-
}
2161
-
};
2162
-
2163
-
syncPreviewWithSelection();
2164
2063
2165
2064
const openEmojiPicker = () => {
2166
2065
if (!emojiPickerOverlay || !emojiPicker) return;
···
2181
2080
if (emojiSearch) emojiSearch.focus();
2182
2081
}, 60);
2183
2082
}
2184
-
2185
-
if (emojiPreviewCurrent) {
2186
-
const currentDisplay = document.querySelector('.current-status .status-emoji');
2187
-
if (currentDisplay) {
2188
-
emojiPreviewCurrent.innerHTML = currentDisplay.innerHTML;
2189
-
} else if (selectedEmoji) {
2190
-
emojiPreviewCurrent.innerHTML = selectedEmoji.innerHTML;
2191
-
}
2192
-
}
2193
-
2194
-
syncPreviewWithSelection();
2195
2083
2196
2084
loadCustomEmojis().then(() => {
2197
2085
loadEmojiCategory('frequent');
···
2314
2202
}
2315
2203
2316
2204
statusInput.value = emoji;
2317
-
syncPreviewWithSelection();
2318
2205
closeEmojiPicker();
2319
2206
checkForChanges();
2320
2207
});
···
2342
2229
// Display the image in the selected emoji area
2343
2230
selectedEmoji.innerHTML = `<img src="${img.src}" alt="${img.alt}" style="width: 100%; height: 100%; object-fit: contain;">`;
2344
2231
statusInput.value = emojiValue;
2345
-
syncPreviewWithSelection();
2346
2232
closeEmojiPicker();
2347
2233
checkForChanges();
2348
2234
});
···
2361
2247
const emoji = e.target.getAttribute('data-emoji');
2362
2248
selectedEmoji.textContent = emoji;
2363
2249
statusInput.value = emoji;
2364
-
syncPreviewWithSelection();
2365
2250
closeEmojiPicker();
2366
2251
checkForChanges();
2367
2252
});
···
2595
2480
}
2596
2481
2597
2482
statusInput.value = emojiValue;
2598
-
syncPreviewWithSelection();
2599
2483
closeEmojiPicker();
2600
2484
checkForChanges();
2601
2485
// Clear search when emoji is selected