Skip to content

Commit faeba8d

Browse files
authored
Merge pull request #57 from XHyperDEVX/cto/implement-login-cookie-ui
Restrict auth to Pollinations login with cookie persistence and gated UI
2 parents 994bce8 + 490ec7c commit faeba8d

3 files changed

Lines changed: 700 additions & 318 deletions

File tree

index.html

Lines changed: 219 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@
196196
.api-key-hint a { color: var(--accent); text-decoration: none; }
197197
.api-key-hint a:hover { text-decoration: underline; }
198198

199-
/* Login Button */
200199
.login-btn {
201200
width: auto;
202201
padding: 6px 12px;
@@ -239,11 +238,6 @@
239238
.login-btn:disabled .login-icon img {
240239
filter: invert(1);
241240
}
242-
.login-or {
243-
font-size: 11px;
244-
color: var(--text-muted);
245-
margin-left: 8px;
246-
}
247241
.login-btn-wrapper {
248242
text-align: center;
249243
display: flex;
@@ -252,6 +246,69 @@
252246
margin-bottom: 8px;
253247
}
254248

249+
.api-key-wrapper {
250+
position: relative;
251+
display: flex;
252+
align-items: center;
253+
}
254+
255+
#api-key {
256+
padding-right: 40px;
257+
}
258+
259+
.copy-api-key-btn {
260+
position: absolute;
261+
right: 8px;
262+
top: 50%;
263+
transform: translateY(-50%);
264+
width: 24px;
265+
height: 24px;
266+
border: 1px solid var(--border-subtle);
267+
border-radius: 6px;
268+
background: #2a2a2c;
269+
color: var(--text-secondary);
270+
display: inline-flex;
271+
align-items: center;
272+
justify-content: center;
273+
cursor: pointer;
274+
transition: border-color 0.2s ease, color 0.2s ease;
275+
}
276+
277+
.copy-api-key-btn:hover {
278+
border-color: var(--accent);
279+
color: #fff;
280+
}
281+
282+
.copy-api-key-btn:disabled {
283+
opacity: 0.45;
284+
cursor: not-allowed;
285+
}
286+
287+
.copy-api-key-btn svg {
288+
width: 14px;
289+
height: 14px;
290+
}
291+
292+
.logout-btn {
293+
position: fixed;
294+
left: 14px;
295+
bottom: 14px;
296+
z-index: 101;
297+
border: 1px solid rgba(255, 255, 255, 0.15);
298+
background: rgba(25, 25, 27, 0.9);
299+
color: var(--text-secondary);
300+
border-radius: 8px;
301+
padding: 7px 10px;
302+
font-size: 11px;
303+
cursor: pointer;
304+
transition: all 0.2s ease;
305+
}
306+
307+
.logout-btn:hover {
308+
color: #fff;
309+
border-color: var(--accent);
310+
}
311+
255312
/* Profile Display in Empty State */
256313
.profile-display {
257314
text-align: center;
@@ -538,11 +595,24 @@
538595

539596
.prompt-bar { min-height: 104px; height: auto; max-height: 300px; background-color: #1a1a1c; border-top: 1px solid var(--border-subtle); padding: 14px 24px; display: flex; align-items: flex-start; gap: 20px; z-index: 60; position: fixed; bottom: 0; left: 360px; right: 0; }
540597
.prompt-bar:hover, .prompt-bar:focus-within { z-index: 200000; }
541-
.prompt-input-wrapper { flex: 1; min-height: 72px; max-height: 200px; height: auto; background-color: #2a2a2c; border-radius: 26px; display: flex; align-items: flex-start; padding: 12px 24px; border: 1px solid #3a3a3c; transition: all 0.3s ease; overflow: visible; }
598+
.prompt-input-wrapper { flex: 1; min-height: 72px; max-height: 200px; height: auto; background-color: #2a2a2c; border-radius: 26px; display: flex; align-items: flex-start; padding: 12px 20px; border: 1px solid #3a3a3c; transition: all 0.3s ease; overflow: hidden; }
542599
.prompt-actions { display: flex; gap: 12px; align-items: stretch; margin-top: auto; align-self: flex-end; flex-shrink: 0; }
543600
.prompt-input-wrapper:focus-within { border-color: var(--accent); background-color: #303033; box-shadow: 0 0 0 4px rgba(37,99,235,0.1); }
544601

545-
#prompt { flex: 1; background: transparent; border: none; color: var(--text-primary); font-size: 15px; outline: none; width: 100%; padding: 0 8px 0 0; resize: none; max-height: 200px; line-height: 1.5; overflow-y: auto; overflow-x: hidden; display: block; scrollbar-width: thin; scrollbar-color: #3a3a3a transparent; scrollbar-gutter: stable; height: auto; min-height: 48px; }
602+
.upload-slots {
603+
display: flex;
604+
flex-direction: column;
605+
gap: 8px;
606+
margin-right: 12px;
607+
}
608+
609+
.upload-slot {
610+
display: flex;
611+
align-items: center;
612+
min-height: 36px;
613+
}
614+
615+
#prompt { flex: 1; background: transparent; border: none; color: var(--text-primary); font-size: 15px; outline: none; width: 100%; padding: 0 2px 0 0; resize: none; max-height: 200px; line-height: 1.5; overflow-y: auto; overflow-x: hidden; display: block; scrollbar-width: thin; scrollbar-color: #3a3a3a transparent; scrollbar-gutter: stable; height: auto; min-height: 48px; }
546616
#prompt::-webkit-scrollbar { width: 6px; }
547617
#prompt::-webkit-scrollbar-track { background: transparent; }
548618
#prompt::-webkit-scrollbar-thumb { background: #3a3a3a; border-radius: 3px; }
@@ -554,9 +624,9 @@
554624
display: flex;
555625
align-items: center;
556626
justify-content: center;
557-
margin-right: 16px;
558-
align-self: flex-start;
559-
margin-top: 4px;
627+
margin-right: 0;
628+
align-self: center;
629+
margin-top: 0;
560630
}
561631

562632

@@ -590,9 +660,9 @@
590660
display: none;
591661
align-items: center;
592662
justify-content: center;
593-
margin-right: 12px;
594-
align-self: flex-start;
595-
margin-top: 2px;
663+
margin-right: 6px;
664+
align-self: center;
665+
margin-top: 0;
596666
}
597667

598668
.upload-thumbnail-wrapper.visible {
@@ -937,6 +1007,55 @@
9371007
background: var(--accent-hover);
9381008
}
9391009

1010+
.auth-gate {
1011+
position: fixed;
1012+
inset: 0;
1013+
background: rgba(7, 7, 9, 0.92);
1014+
backdrop-filter: blur(5px);
1015+
z-index: 120000;
1016+
display: flex;
1017+
align-items: center;
1018+
justify-content: center;
1019+
padding: 20px;
1020+
}
1021+
1022+
.auth-popup {
1023+
width: min(460px, 100%);
1024+
background: var(--panel-bg);
1025+
border: 1px solid var(--border-subtle);
1026+
border-radius: 16px;
1027+
padding: 24px;
1028+
text-align: center;
1029+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
1030+
}
1031+
1032+
.auth-popup-logo {
1033+
width: 58px;
1034+
height: 58px;
1035+
border-radius: 12px;
1036+
margin-bottom: 14px;
1037+
}
1038+
1039+
.auth-popup h2 {
1040+
font-size: 22px;
1041+
margin-bottom: 10px;
1042+
}
1043+
1044+
.auth-popup p {
1045+
color: var(--text-secondary);
1046+
font-size: 14px;
1047+
margin-bottom: 18px;
1048+
line-height: 1.45;
1049+
}
1050+
1051+
body.auth-locked .sidebar,
1052+
body.auth-locked .canvas,
1053+
body.auth-locked .api-key-container,
1054+
body.auth-locked #logout-btn {
1055+
pointer-events: none;
1056+
user-select: none;
1057+
}
1058+
9401059
</style>
9411060
</head>
9421061
<body>
@@ -1040,13 +1159,22 @@ <h3 data-i18n="advancedLabel">Advanced Options</h3>
10401159
</span>
10411160
<span id="login-btn-text" data-i18n="loginWithPollinations">Login with Pollinations</span>
10421161
</button>
1043-
<span class="login-or" data-i18n="orLabel">or</span>
10441162
</div>
1045-
<div class="api-key-wrapper"><input type="password" id="api-key" data-i18n-placeholder="apiKeyPlaceholder" placeholder="API Key" autocomplete="current-password"></div>
1163+
<div class="api-key-wrapper">
1164+
<input type="password" id="api-key" data-i18n-placeholder="apiKeyPlaceholder" placeholder="API Key" autocomplete="off" readonly>
1165+
<button class="copy-api-key-btn" id="copy-api-key-btn" type="button" title="Copy API key" aria-label="Copy API key">
1166+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1167+
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
1168+
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
1169+
</svg>
1170+
</button>
1171+
</div>
10461172
<div id="api-key-hint" class="api-key-hint" data-i18n="apiKeyHint">Get your API key from <a href="https://pollinations.ai" target="_blank">Pollinations</a></div>
10471173
<div id="resolution-warning" class="resolution-warning" data-i18n="resolutionWarning">For optimal use, a resolution of at least 1080p is recommended.</div>
10481174
</div>
10491175

1176+
<button class="logout-btn hidden" id="logout-btn" type="button" data-i18n="logoutLabel">Logout</button>
1177+
10501178
<main class="canvas">
10511179
<div class="canvas-workspace" id="canvas-workspace">
10521180
<div class="empty-state" id="placeholder">
@@ -1067,63 +1195,69 @@ <h2 id="empty-title" data-i18n="startScreenTitle">Generate Images Now</h2>
10671195

10681196
<div class="prompt-bar">
10691197
<div class="prompt-input-wrapper">
1070-
<div class="upload-thumbnail-wrapper" id="upload-thumbnail-wrapper">
1071-
<img class="upload-thumbnail-preview" id="upload-thumbnail-preview" src="" alt="Preview">
1072-
<img class="upload-thumbnail" id="upload-thumbnail" src="" alt="Uploaded image">
1073-
<div class="upload-thumbnail-delete" id="upload-thumbnail-delete" title="Remove image">
1074-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
1075-
<line x1="18" y1="6" x2="6" y2="18"></line>
1076-
<line x1="6" y1="6" x2="18" y2="18"></line>
1077-
</svg>
1078-
</div>
1079-
<div class="upload-progress" id="upload-progress" style="display: none;">
1080-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1081-
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
1082-
</svg>
1083-
</div>
1084-
<div class="upload-delete-progress" id="upload-delete-progress" style="display: none;">
1085-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1086-
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
1087-
</svg>
1088-
</div>
1089-
</div>
1090-
<div class="upload-icon-container" id="upload-icon-container" title="">
1091-
<svg class="upload-icon" id="upload-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1092-
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
1093-
<polyline points="17,8 12,3 7,8"></polyline>
1094-
<line x1="12" y1="3" x2="12" y2="15"></line>
1095-
</svg>
1096-
</div>
1097-
<input type="file" id="image-upload-input" accept="image/*" style="display: none;">
1098-
1099-
<div class="upload-thumbnail-wrapper" id="upload-thumbnail-wrapper-2">
1100-
<img class="upload-thumbnail-preview" id="upload-thumbnail-preview-2" src="" alt="Preview">
1101-
<img class="upload-thumbnail" id="upload-thumbnail-2" src="" alt="Uploaded image 2">
1102-
<div class="upload-thumbnail-delete" id="upload-thumbnail-delete-2" title="Remove image">
1103-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
1104-
<line x1="18" y1="6" x2="6" y2="18"></line>
1105-
<line x1="6" y1="6" x2="18" y2="18"></line>
1106-
</svg>
1107-
</div>
1108-
<div class="upload-progress" id="upload-progress-2" style="display: none;">
1109-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1110-
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
1111-
</svg>
1198+
<div class="upload-slots">
1199+
<div class="upload-slot">
1200+
<div class="upload-thumbnail-wrapper" id="upload-thumbnail-wrapper">
1201+
<img class="upload-thumbnail-preview" id="upload-thumbnail-preview" src="" alt="Preview">
1202+
<img class="upload-thumbnail" id="upload-thumbnail" src="" alt="Uploaded image">
1203+
<div class="upload-thumbnail-delete" id="upload-thumbnail-delete" title="Remove image">
1204+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
1205+
<line x1="18" y1="6" x2="6" y2="18"></line>
1206+
<line x1="6" y1="6" x2="18" y2="18"></line>
1207+
</svg>
1208+
</div>
1209+
<div class="upload-progress" id="upload-progress" style="display: none;">
1210+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1211+
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
1212+
</svg>
1213+
</div>
1214+
<div class="upload-delete-progress" id="upload-delete-progress" style="display: none;">
1215+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1216+
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
1217+
</svg>
1218+
</div>
1219+
</div>
1220+
<div class="upload-icon-container" id="upload-icon-container" title="">
1221+
<svg class="upload-icon" id="upload-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1222+
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
1223+
<polyline points="17,8 12,3 7,8"></polyline>
1224+
<line x1="12" y1="3" x2="12" y2="15"></line>
1225+
</svg>
1226+
</div>
1227+
<input type="file" id="image-upload-input" accept="image/*" style="display: none;">
11121228
</div>
1113-
<div class="upload-delete-progress" id="upload-delete-progress-2" style="display: none;">
1114-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1115-
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
1116-
</svg>
1229+
1230+
<div class="upload-slot">
1231+
<div class="upload-thumbnail-wrapper" id="upload-thumbnail-wrapper-2">
1232+
<img class="upload-thumbnail-preview" id="upload-thumbnail-preview-2" src="" alt="Preview">
1233+
<img class="upload-thumbnail" id="upload-thumbnail-2" src="" alt="Uploaded image 2">
1234+
<div class="upload-thumbnail-delete" id="upload-thumbnail-delete-2" title="Remove image">
1235+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
1236+
<line x1="18" y1="6" x2="6" y2="18"></line>
1237+
<line x1="6" y1="6" x2="18" y2="18"></line>
1238+
</svg>
1239+
</div>
1240+
<div class="upload-progress" id="upload-progress-2" style="display: none;">
1241+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1242+
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
1243+
</svg>
1244+
</div>
1245+
<div class="upload-delete-progress" id="upload-delete-progress-2" style="display: none;">
1246+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1247+
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
1248+
</svg>
1249+
</div>
1250+
</div>
1251+
<div class="upload-icon-container" id="upload-icon-container-2" title="">
1252+
<svg class="upload-icon" id="upload-icon-2" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1253+
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
1254+
<polyline points="17,8 12,3 7,8"></polyline>
1255+
<line x1="12" y1="3" x2="12" y2="15"></line>
1256+
</svg>
1257+
</div>
1258+
<input type="file" id="image-upload-input-2" accept="image/*" style="display: none;">
11171259
</div>
11181260
</div>
1119-
<div class="upload-icon-container" id="upload-icon-container-2" title="">
1120-
<svg class="upload-icon" id="upload-icon-2" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1121-
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
1122-
<polyline points="17,8 12,3 7,8"></polyline>
1123-
<line x1="12" y1="3" x2="12" y2="15"></line>
1124-
</svg>
1125-
</div>
1126-
<input type="file" id="image-upload-input-2" accept="image/*" style="display: none;">
11271261
<textarea id="prompt" data-i18n-placeholder="promptPlaceholder" placeholder="Describe the image you want to generate" rows="2"></textarea>
11281262
</div>
11291263
<div class="prompt-actions">
@@ -1222,6 +1356,21 @@ <h2 id="empty-title" data-i18n="startScreenTitle">Generate Images Now</h2>
12221356
<span data-i18n="useAsReferenceImage">Use as reference image</span>
12231357
</div>
12241358
</div>
1359+
1360+
<div id="auth-gate" class="auth-gate hidden">
1361+
<div class="auth-popup">
1362+
<img class="auth-popup-logo" src="js/icon.png" alt="Pollgen">
1363+
<h2 data-i18n="welcomePopupTitle">Welcome to Pollgen</h2>
1364+
<p data-i18n="welcomePopupText">Create AI images and videos with Pollinations. Log in to continue.</p>
1365+
<button class="login-btn" id="auth-popup-login-btn" type="button">
1366+
<span class="login-icon">
1367+
<img src="https://raw.githubusercontent.com/pollinations/pollinations/refs/heads/main/assets/logo.svg" alt="">
1368+
</span>
1369+
<span data-i18n="loginWithPollinations">Login with Pollinations</span>
1370+
</button>
1371+
</div>
1372+
</div>
1373+
12251374
<form id="generation-form" style="display: none;">
12261375
<input type="hidden" name="width" id="width" value="1366">
12271376
<input type="hidden" name="height" id="height" value="1025">

0 commit comments

Comments
 (0)