HTML_JS_ETC / N Priva Comment Generator /N Priva Comment Generator.html
nzgnzg73's picture
Upload N Priva Comment Generator.html
5da0f26 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>N Priva Comment Generator</title>
<!-- html2canvas library for image export - START -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<!-- html2canvas library for image export - END -->
<style>
/* ============================================
CSS STYLES - START
============================================ */
/* Google Fonts Import - START */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
/* Google Fonts Import - END */
/* CSS Variables for Theme - START */
:root {
--bg-primary: #ffffff;
--bg-secondary: #f5f5f5;
--bg-card: #ffffff;
--text-primary: #161823;
--text-secondary: #545454;
--text-muted: #8a8a8a;
--border-color: #e3e3e3;
--accent-color: #fe2c55;
--accent-hover: #e91e45;
--verified-color: #20d5ec;
--shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
--input-bg: #f1f1f2;
}
[data-theme="dark"] {
--bg-primary: #121212;
--bg-secondary: #1e1e1e;
--bg-card: #1e1e1e;
--text-primary: #ffffff;
--text-secondary: #b0b0b0;
--text-muted: #6a6a6a;
--border-color: #2f2f2f;
--shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
--input-bg: #2a2a2a;
}
/* CSS Variables for Theme - END */
/* Global Styles - START */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
transition: all 0.3s ease;
}
/* Global Styles - END */
/* Header Styles - START */
.header {
background: linear-gradient(135deg, #fe2c55 0%, #25f4ee 100%);
padding: 30px 20px;
text-align: center;
position: relative;
}
.header h1 {
color: white;
font-size: 2.5rem;
font-weight: 700;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
}
.header h1 .logo-icon {
width: 50px;
height: 50px;
background: white;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.8rem;
}
.header p {
color: rgba(255, 255, 255, 0.9);
margin-top: 10px;
font-size: 1.1rem;
}
.theme-toggle {
position: absolute;
top: 20px;
right: 20px;
background: rgba(255, 255, 255, 0.2);
border: none;
padding: 12px 20px;
border-radius: 25px;
color: white;
cursor: pointer;
font-size: 1rem;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
}
.theme-toggle:hover {
background: rgba(255, 255, 255, 0.3);
transform: scale(1.05);
}
/* Header Styles - END */
/* Main Container - START */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
}
@media (max-width: 900px) {
.container {
grid-template-columns: 1fr;
}
}
/* Main Container - END */
/* Card Styles - START */
.card {
background: var(--bg-card);
border-radius: 20px;
padding: 30px;
box-shadow: var(--shadow);
border: 1px solid var(--border-color);
}
.card-title {
font-size: 1.4rem;
font-weight: 600;
margin-bottom: 25px;
display: flex;
align-items: center;
gap: 10px;
color: var(--text-primary);
}
.card-title .icon {
width: 35px;
height: 35px;
background: linear-gradient(135deg, #fe2c55, #ff6b81);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
/* Card Styles - END */
/* Form Elements - START */
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: var(--text-secondary);
font-size: 0.95rem;
}
.form-group input[type="text"],
.form-group textarea {
width: 100%;
padding: 14px 18px;
border: 2px solid var(--border-color);
border-radius: 12px;
font-size: 1rem;
background: var(--input-bg);
color: var(--text-primary);
transition: all 0.3s ease;
}
.form-group input[type="text"]:focus,
.form-group textarea:focus {
outline: none;
border-color: var(--accent-color);
box-shadow: 0 0 0 4px rgba(254, 44, 85, 0.1);
}
.form-group textarea {
resize: vertical;
min-height: 100px;
}
/* Form Elements - END */
/* Toggle Switch - START */
.toggle-group {
display: flex;
align-items: center;
justify-content: space-between;
padding: 15px;
background: var(--input-bg);
border-radius: 12px;
margin-bottom: 15px;
}
.toggle-label {
display: flex;
align-items: center;
gap: 10px;
font-weight: 500;
color: var(--text-primary);
}
.toggle-switch {
position: relative;
width: 55px;
height: 30px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--border-color);
transition: 0.3s;
border-radius: 30px;
}
.toggle-slider:before {
position: absolute;
content: "";
height: 24px;
width: 24px;
left: 3px;
bottom: 3px;
background-color: white;
transition: 0.3s;
border-radius: 50%;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.toggle-switch input:checked+.toggle-slider {
background: linear-gradient(135deg, #20d5ec, #25f4ee);
}
.toggle-switch input:checked+.toggle-slider:before {
transform: translateX(25px);
}
/* Toggle Switch - END */
/* Random Identity Buttons - START */
.identity-section {
margin-bottom: 25px;
}
.identity-section h3 {
font-size: 1rem;
color: var(--text-secondary);
margin-bottom: 15px;
font-weight: 500;
}
.identity-buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
}
.identity-btn {
padding: 15px 10px;
border: 2px solid var(--border-color);
border-radius: 12px;
background: var(--input-bg);
color: var(--text-primary);
cursor: pointer;
font-size: 0.9rem;
font-weight: 500;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}
.identity-btn:hover {
border-color: var(--accent-color);
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(254, 44, 85, 0.2);
}
.identity-btn .icon {
font-size: 1.8rem;
}
.identity-btn.male:hover {
border-color: #3b82f6;
background: rgba(59, 130, 246, 0.1);
}
.identity-btn.female:hover {
border-color: #ec4899;
background: rgba(236, 72, 153, 0.1);
}
.identity-btn.celebrity:hover {
border-color: #f59e0b;
background: rgba(245, 158, 11, 0.1);
}
.identity-btn.realistic:hover {
border-color: #10b981;
background: rgba(16, 185, 129, 0.1);
}
/* Random Identity Buttons - END */
/* Profile Picture Section - START */
.profile-upload {
display: flex;
align-items: center;
gap: 20px;
padding: 20px;
background: var(--input-bg);
border-radius: 15px;
margin-bottom: 20px;
}
.profile-preview {
width: 70px;
height: 70px;
border-radius: 50%;
object-fit: cover;
border: 3px solid var(--accent-color);
}
.profile-upload-area {
flex: 1;
}
.upload-btn {
padding: 12px 20px;
background: var(--accent-color);
color: white;
border: none;
border-radius: 10px;
cursor: pointer;
font-weight: 500;
transition: all 0.3s ease;
}
.upload-btn:hover {
background: var(--accent-hover);
}
.upload-hint {
font-size: 0.85rem;
color: var(--text-muted);
margin-top: 8px;
}
#profileInput {
display: none;
}
/* Profile Picture Section - END */
/* Message Style Section - START */
.message-style-section {
margin-bottom: 25px;
}
.message-style-section h3 {
font-size: 1rem;
color: var(--text-secondary);
margin-bottom: 15px;
font-weight: 500;
}
.style-buttons {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.style-btn {
padding: 15px 10px;
border: 2px solid var(--border-color);
border-radius: 12px;
background: var(--input-bg);
color: var(--text-primary);
cursor: pointer;
font-size: 0.85rem;
font-weight: 500;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}
.style-btn:hover {
border-color: var(--accent-color);
transform: translateY(-2px);
}
.style-btn.active {
border-color: var(--accent-color);
background: rgba(254, 44, 85, 0.1);
}
.style-btn .icon {
font-size: 1.5rem;
}
/* Message Style Section - END */
/* Advanced Edit Section - START */
.advanced-section {
border-top: 1px solid var(--border-color);
padding-top: 20px;
margin-top: 20px;
}
.advanced-toggle {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
padding: 15px;
background: var(--input-bg);
border-radius: 12px;
margin-bottom: 15px;
}
.advanced-toggle:hover {
background: var(--border-color);
}
.advanced-content {
display: none;
padding: 15px;
background: var(--input-bg);
border-radius: 12px;
margin-top: 10px;
}
.advanced-content.show {
display: block;
animation: slideDown 0.3s ease;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.blur-slider {
width: 100%;
margin-top: 10px;
}
.blur-value {
text-align: center;
font-weight: 600;
color: var(--accent-color);
margin-top: 5px;
}
/* Advanced Edit Section - END */
/* Comment Preview Section - START */
.preview-section {
position: sticky;
top: 20px;
}
.comment-preview {
background: var(--bg-card);
border-radius: 20px;
padding: 25px;
border: 1px solid var(--border-color);
}
/* Default Style - Style 1 */
.comment-container {
display: flex;
gap: 15px;
padding: 20px;
background: var(--input-bg);
border-radius: 15px;
transition: all 0.3s ease;
}
/* Bubble Style - Style 2 */
.comment-container.style-bubble {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 20px 20px 20px 5px;
position: relative;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
.comment-container.style-bubble::after {
content: '';
position: absolute;
bottom: 0;
left: -10px;
width: 0;
height: 0;
border: 15px solid transparent;
border-right-color: #764ba2;
border-bottom-color: #764ba2;
border-left: 0;
margin-bottom: -5px;
}
.comment-container.style-bubble .comment-username,
.comment-container.style-bubble .comment-text,
.comment-container.style-bubble .comment-time,
.comment-container.style-bubble .comment-action {
color: white !important;
}
/* Card Style - Style 3 */
.comment-container.style-card {
background: var(--bg-card);
border: 2px solid var(--accent-color);
border-radius: 16px;
box-shadow: 0 8px 30px rgba(254, 44, 85, 0.15);
padding: 25px;
}
.comment-avatar {
width: 48px;
height: 48px;
border-radius: 50%;
object-fit: cover;
flex-shrink: 0;
}
.comment-content {
flex: 1;
}
.comment-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 6px;
}
.comment-username {
font-weight: 600;
font-size: 0.95rem;
color: var(--text-primary);
}
.verified-badge {
width: 16px;
height: 16px;
display: none;
}
.verified-badge.show {
display: inline-block;
}
.comment-time {
font-size: 0.8rem;
color: var(--text-muted);
}
.comment-text {
font-size: 0.95rem;
color: var(--text-primary);
line-height: 1.5;
word-wrap: break-word;
}
.comment-text.blurred {
filter: blur(var(--blur-amount, 0px));
}
.comment-actions {
display: flex;
align-items: center;
gap: 20px;
margin-top: 12px;
}
.comment-action {
display: flex;
align-items: center;
gap: 5px;
color: var(--text-muted);
font-size: 0.85rem;
}
.comment-action .heart {
color: #fe2c55;
}
.like-action {
display: flex;
align-items: center;
gap: 5px;
}
.like-action.hidden {
display: none;
}
/* Comment Preview Section - END */
/* Export Buttons - START */
.export-section {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
margin-top: 25px;
}
.export-btn {
padding: 16px 25px;
border: none;
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
transition: all 0.3s ease;
}
.export-btn.download {
background: linear-gradient(135deg, #fe2c55, #ff6b81);
color: white;
}
.export-btn.download:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(254, 44, 85, 0.4);
}
.export-btn.copy {
background: linear-gradient(135deg, #25f4ee, #20d5ec);
color: white;
}
.export-btn.copy:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(32, 213, 236, 0.4);
}
/* Export Buttons - END */
/* Notification Toast - START */
.toast {
position: fixed;
bottom: 30px;
left: 50%;
transform: translateX(-50%) translateY(100px);
background: #1e1e1e;
color: white;
padding: 16px 30px;
border-radius: 12px;
font-weight: 500;
z-index: 1000;
opacity: 0;
transition: all 0.4s ease;
display: flex;
align-items: center;
gap: 10px;
}
.toast.show {
transform: translateX(-50%) translateY(0);
opacity: 1;
}
.toast.success {
background: linear-gradient(135deg, #10b981, #059669);
}
/* Notification Toast - END */
/* Footer - START */
.footer {
text-align: center;
padding: 30px;
color: var(--text-muted);
font-size: 0.9rem;
}
.footer a {
color: var(--accent-color);
text-decoration: none;
}
/* Footer - END */
/* Style Switcher in Preview - START */
.style-switcher {
display: flex;
gap: 10px;
margin-bottom: 20px;
justify-content: center;
}
.style-switch-btn {
padding: 10px 20px;
border: 2px solid var(--border-color);
border-radius: 25px;
background: var(--input-bg);
color: var(--text-primary);
cursor: pointer;
font-size: 0.85rem;
font-weight: 500;
transition: all 0.3s ease;
}
.style-switch-btn:hover {
border-color: var(--accent-color);
}
.style-switch-btn.active {
background: var(--accent-color);
color: white;
border-color: var(--accent-color);
}
/* Style Switcher in Preview - END */
/* Responsive Styles - START */
@media (max-width: 600px) {
.header h1 {
font-size: 1.8rem;
}
.theme-toggle {
position: static;
margin-top: 15px;
}
.identity-buttons {
grid-template-columns: repeat(2, 1fr);
}
.style-buttons {
grid-template-columns: 1fr;
}
.export-section {
grid-template-columns: 1fr;
}
.card {
padding: 20px;
}
.style-switcher {
flex-wrap: wrap;
}
}
/* Responsive Styles - END */
/* ============================================
CSS STYLES - END
============================================ */
</style>
</head>
<body data-theme="light">
<!-- ============================================
HEADER SECTION - START
============================================ -->
<header class="header">
<h1>
<span class="logo-icon">🎵</span>
N Priva Comment Generator
</h1>
<p>Create realistic TikTok-style comments in seconds</p>
<button class="theme-toggle" onclick="toggleTheme()">
<span id="themeIcon">🌙</span>
<span id="themeText">Dark Mode</span>
</button>
</header>
<!-- ============================================
HEADER SECTION - END
============================================ -->
<!-- ============================================
MAIN CONTAINER - START
============================================ -->
<main class="container">
<!-- ============================================
EDITOR PANEL - START
============================================ -->
<div class="card editor-panel">
<h2 class="card-title">
<span class="icon">✏️</span>
Comment Editor
</h2>
<!-- Random Identity Generator - START -->
<div class="identity-section">
<h3>🎲 Random Identity Generator</h3>
<div class="identity-buttons">
<button class="identity-btn male" onclick="generateIdentity('male')">
<span class="icon">👨</span>
Male
</button>
<button class="identity-btn female" onclick="generateIdentity('female')">
<span class="icon">👩</span>
Female
</button>
<button class="identity-btn celebrity" onclick="generateIdentity('celebrity')">
<span class="icon"></span>
Celebrity
</button>
<!-- NEW: Realistic Button - START -->
<button class="identity-btn realistic" onclick="generateIdentity('realistic')">
<span class="icon">📸</span>
Realistic
</button>
<!-- NEW: Realistic Button - END -->
</div>
</div>
<!-- Random Identity Generator - END -->
<!-- Profile Picture Upload - START -->
<div class="profile-upload">
<img src="https://api.dicebear.com/7.x/avataaars/svg?seed=default" alt="Profile" class="profile-preview"
id="profilePreview">
<div class="profile-upload-area">
<button class="upload-btn" onclick="document.getElementById('profileInput').click()">
📷 Upload Photo
</button>
<p class="upload-hint">Or use Random Identity above</p>
<input type="file" id="profileInput" accept="image/*" onchange="handleImageUpload(event)">
</div>
</div>
<!-- Profile Picture Upload - END -->
<!-- Username Input - START -->
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" placeholder="Enter username..." value="user_name"
oninput="updatePreview()">
</div>
<!-- Username Input - END -->
<!-- Comment Text Input - START -->
<div class="form-group">
<label for="commentText">Comment Text</label>
<textarea id="commentText" placeholder="Write your comment here..."
oninput="updatePreview()">This is an amazing video! 🔥❤️</textarea>
</div>
<!-- Comment Text Input - END -->
<!-- Like Count Input - START -->
<div class="form-group">
<label for="likeCount">Like Count</label>
<input type="text" id="likeCount" placeholder="e.g., 1.2K" value="2.5K" oninput="updatePreview()">
</div>
<!-- Like Count Input - END -->
<!-- NEW: Show Like Icon Toggle - START -->
<div class="toggle-group">
<span class="toggle-label">
<span>❤️</span>
Show Like Icon
</span>
<label class="toggle-switch">
<input type="checkbox" id="likeIconToggle" checked onchange="updatePreview()">
<span class="toggle-slider"></span>
</label>
</div>
<!-- NEW: Show Like Icon Toggle - END -->
<!-- Time Ago Input - START -->
<div class="form-group">
<label for="timeAgo">Time</label>
<input type="text" id="timeAgo" placeholder="e.g., 2h, 1d, 3w" value="2h" oninput="updatePreview()">
</div>
<!-- Time Ago Input - END -->
<!-- Verified Badge Toggle - START -->
<div class="toggle-group">
<span class="toggle-label">
<span></span>
Verified Badge (Blue Tick)
</span>
<label class="toggle-switch">
<input type="checkbox" id="verifiedToggle" onchange="updatePreview()">
<span class="toggle-slider"></span>
</label>
</div>
<!-- Verified Badge Toggle - END -->
<!-- NEW: Message Style Section - START -->
<div class="message-style-section">
<h3>💬 Advanced Message Styles</h3>
<div class="style-buttons">
<button class="style-btn active" onclick="changeMessageStyle('default')" id="styleDefault">
<span class="icon">📝</span>
Default
</button>
<button class="style-btn" onclick="changeMessageStyle('bubble')" id="styleBubble">
<span class="icon">💭</span>
Bubble
</button>
<button class="style-btn" onclick="changeMessageStyle('card')" id="styleCard">
<span class="icon">🎴</span>
Card
</button>
</div>
</div>
<!-- NEW: Message Style Section - END -->
<!-- Advanced Edit Section - START -->
<div class="advanced-section">
<div class="advanced-toggle" onclick="toggleAdvanced()">
<span class="toggle-label">
<span>⚙️</span>
Advanced Edit
</span>
<span id="advancedArrow"></span>
</div>
<div class="advanced-content" id="advancedContent">
<!-- Blur Text Option - START -->
<div class="form-group">
<label for="blurSlider">Blur Text Effect</label>
<input type="range" id="blurSlider" class="blur-slider" min="0" max="10" value="0"
oninput="updateBlur()">
<p class="blur-value" id="blurValue">0px</p>
</div>
<!-- Blur Text Option - END -->
<!-- Reply Count Toggle - START -->
<div class="toggle-group">
<span class="toggle-label">
<span>💬</span>
Show Reply Count
</span>
<label class="toggle-switch">
<input type="checkbox" id="replyToggle" checked onchange="updatePreview()">
<span class="toggle-slider"></span>
</label>
</div>
<!-- Reply Count Toggle - END -->
<!-- Reply Count Input - START -->
<div class="form-group" id="replyCountGroup">
<label for="replyCount">Reply Count</label>
<input type="text" id="replyCount" placeholder="e.g., 50" value="12" oninput="updatePreview()">
</div>
<!-- Reply Count Input - END -->
</div>
</div>
<!-- Advanced Edit Section - END -->
</div>
<!-- ============================================
EDITOR PANEL - END
============================================ -->
<!-- ============================================
PREVIEW PANEL - START
============================================ -->
<div class="card preview-section">
<h2 class="card-title">
<span class="icon">👁️</span>
Live Preview
</h2>
<!-- Style Switcher Buttons - START -->
<div class="style-switcher">
<button class="style-switch-btn active" onclick="switchPreviewStyle('default')"
id="previewStyleDefault">
Style 1
</button>
<button class="style-switch-btn" onclick="switchPreviewStyle('bubble')" id="previewStyleBubble">
Style 2
</button>
<button class="style-switch-btn" onclick="switchPreviewStyle('card')" id="previewStyleCard">
Style 3
</button>
</div>
<!-- Style Switcher Buttons - END -->
<!-- Comment Preview Box - START -->
<div class="comment-preview" id="commentPreview">
<div class="comment-container" id="commentContainer">
<img src="https://api.dicebear.com/7.x/avataaars/svg?seed=default" alt="Avatar"
class="comment-avatar" id="commentAvatar">
<div class="comment-content">
<div class="comment-header">
<span class="comment-username" id="previewUsername">user_name</span>
<!-- Verified Badge SVG - START -->
<svg class="verified-badge" id="verifiedBadge" viewBox="0 0 20 20" fill="#20d5ec">
<path fill-rule="evenodd"
d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clip-rule="evenodd" />
</svg>
<!-- Verified Badge SVG - END -->
<span class="comment-time" id="previewTime">2h</span>
</div>
<p class="comment-text" id="previewText">This is an amazing video! 🔥❤️</p>
<div class="comment-actions">
<!-- Like Action with Toggle - START -->
<span class="comment-action like-action" id="likeAction">
<span class="heart">❤️</span>
<span id="previewLikes">2.5K</span>
</span>
<!-- Like Action with Toggle - END -->
<span class="comment-action" id="replyAction">
<span>💬</span>
<span id="previewReplies">12</span> replies
</span>
</div>
</div>
</div>
</div>
<!-- Comment Preview Box - END -->
<!-- Export Buttons - START -->
<div class="export-section">
<button class="export-btn download" onclick="downloadImage()">
<span>📥</span>
Download Image
</button>
<button class="export-btn copy" onclick="copyToClipboard()">
<span>📋</span>
Copy to Clipboard
</button>
</div>
<!-- Export Buttons - END -->
</div>
<!-- ============================================
PREVIEW PANEL - END
============================================ -->
</main>
<!-- ============================================
MAIN CONTAINER - END
============================================ -->
<!-- ============================================
TOAST NOTIFICATION - START
============================================ -->
<div class="toast" id="toast">
<span id="toastIcon"></span>
<span id="toastMessage">Success!</span>
</div>
<!-- ============================================
TOAST NOTIFICATION - END
============================================ -->
<!-- ============================================
FOOTER SECTION - START
============================================ -->
<footer class="footer">
<p>Made with ❤️ by N Priva | Generate unlimited TikTok-style comments</p>
</footer>
<!-- ============================================
FOOTER SECTION - END
============================================ -->
<!-- ============================================
JAVASCRIPT CODE - START
============================================ -->
<script>
// ============================================
// DATA ARRAYS FOR RANDOM IDENTITY - START
// ============================================
// Male Names Array - START
const maleNames = [
'james_smith', 'michael_johnson', 'david_williams', 'chris_brown',
'daniel_jones', 'matthew_davis', 'andrew_miller', 'joshua_wilson',
'ryan_taylor', 'brandon_anderson', 'kevin_thomas', 'jason_jackson',
'justin_white', 'tyler_harris', 'austin_martin', 'zachary_thompson',
'alex_garcia', 'nathan_martinez', 'adam_robinson', 'ethan_clark'
];
// Male Names Array - END
// Female Names Array - START
const femaleNames = [
'emma_watson', 'olivia_jones', 'sophia_williams', 'isabella_brown',
'mia_johnson', 'charlotte_davis', 'amelia_miller', 'harper_wilson',
'evelyn_moore', 'abigail_taylor', 'emily_anderson', 'elizabeth_thomas',
'avery_jackson', 'ella_white', 'scarlett_harris', 'grace_martin',
'lily_thompson', 'chloe_garcia', 'victoria_martinez', 'riley_robinson'
];
// Female Names Array - END
// Celebrity Names Array - START
const celebrityNames = [
'therock', 'kyliejenner', 'kimkardashian', 'selenagomez',
'arianagrande', 'beyonce', 'taylorswift', 'justinbieber',
'cristiano', 'leomessi', 'neymarjr', 'kingjames',
'travisscott', 'nickiminaj', 'badgalriri', 'theweeknd',
'billieeilish', 'charlidamelio', 'addisonraee', 'khloekardashian'
];
// Celebrity Names Array - END
// Realistic Names Array - START
const realisticNames = [
'john_doe_99', 'sarah_miller', 'mike_wilson', 'emily_davis',
'alex_johnson', 'jessica_brown', 'david_smith', 'amanda_jones',
'chris_taylor', 'ashley_anderson', 'ryan_thomas', 'stephanie_white',
'kevin_martin', 'nicole_garcia', 'brian_martinez', 'michelle_robinson',
'jason_lee', 'jennifer_clark', 'mark_lewis', 'lisa_walker'
];
// Realistic Names Array - END
// Current Style Variable
let currentStyle = 'default';
// ============================================
// DATA ARRAYS FOR RANDOM IDENTITY - END
// ============================================
// ============================================
// THEME TOGGLE FUNCTION - START
// ============================================
function toggleTheme() {
const body = document.body;
const themeIcon = document.getElementById('themeIcon');
const themeText = document.getElementById('themeText');
if (body.getAttribute('data-theme') === 'light') {
body.setAttribute('data-theme', 'dark');
themeIcon.textContent = '☀️';
themeText.textContent = 'Light Mode';
} else {
body.setAttribute('data-theme', 'light');
themeIcon.textContent = '🌙';
themeText.textContent = 'Dark Mode';
}
}
// ============================================
// THEME TOGGLE FUNCTION - END
// ============================================
// ============================================
// LIVE PREVIEW UPDATE FUNCTION - START
// ============================================
function updatePreview() {
// Get Input Values - START
const username = document.getElementById('username').value || 'username';
const commentText = document.getElementById('commentText').value || 'Your comment here...';
const likeCount = document.getElementById('likeCount').value || '0';
const timeAgo = document.getElementById('timeAgo').value || '1h';
const replyCount = document.getElementById('replyCount').value || '0';
const isVerified = document.getElementById('verifiedToggle').checked;
const showReplies = document.getElementById('replyToggle').checked;
const showLikeIcon = document.getElementById('likeIconToggle').checked;
// Get Input Values - END
// Update Preview Elements - START
document.getElementById('previewUsername').textContent = username;
document.getElementById('previewText').textContent = commentText;
document.getElementById('previewLikes').textContent = likeCount;
document.getElementById('previewTime').textContent = timeAgo;
document.getElementById('previewReplies').textContent = replyCount;
// Update Preview Elements - END
// Toggle Verified Badge - START
const verifiedBadge = document.getElementById('verifiedBadge');
if (isVerified) {
verifiedBadge.classList.add('show');
} else {
verifiedBadge.classList.remove('show');
}
// Toggle Verified Badge - END
// Toggle Like Icon - START
const likeAction = document.getElementById('likeAction');
if (showLikeIcon) {
likeAction.classList.remove('hidden');
} else {
likeAction.classList.add('hidden');
}
// Toggle Like Icon - END
// Toggle Reply Section - START
const replyAction = document.getElementById('replyAction');
const replyCountGroup = document.getElementById('replyCountGroup');
if (showReplies) {
replyAction.style.display = 'flex';
replyCountGroup.style.display = 'block';
} else {
replyAction.style.display = 'none';
replyCountGroup.style.display = 'none';
}
// Toggle Reply Section - END
}
// ============================================
// LIVE PREVIEW UPDATE FUNCTION - END
// ============================================
// ============================================
// RANDOM IDENTITY GENERATOR FUNCTION - START
// ============================================
// ============================================
// HELPER TO FETCH IMAGE AS BASE64 - START
// ============================================
async function fetchImageAsBase64(url) {
// Helper to convert blob to base64
const blobToBase64 = (blob) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
};
try {
// Try direct fetch first
const response = await fetch(url);
if (!response.ok) throw new Error('Direct fetch failed');
const blob = await response.blob();
return await blobToBase64(blob);
} catch (directError) {
console.warn('Direct fetch failed, trying proxy...', directError);
try {
// Fallback to CORS proxy
// Using corsproxy.io as a reliable public proxy
const proxyUrl = 'https://corsproxy.io/?' + encodeURIComponent(url);
const response = await fetch(proxyUrl);
if (!response.ok) throw new Error('Proxy fetch failed');
const blob = await response.blob();
return await blobToBase64(blob);
} catch (proxyError) {
console.error('Error fetching image via proxy:', proxyError);
return null;
}
}
}
// ============================================
// HELPER TO FETCH IMAGE AS BASE64 - END
// ============================================
// ============================================
// RANDOM IDENTITY GENERATOR FUNCTION - START
// ============================================
async function generateIdentity(type) {
let name;
let avatarUrl;
// Select Name and Avatar Based on Type - START
if (type === 'male') {
name = maleNames[Math.floor(Math.random() * maleNames.length)];
// CHANGED: Using .png instead of .svg to fix download distortion
avatarUrl = `https://api.dicebear.com/7.x/avataaars/png?seed=male${Math.random()}`;
} else if (type === 'female') {
name = femaleNames[Math.floor(Math.random() * femaleNames.length)];
// CHANGED: Using .png instead of .svg to fix download distortion
avatarUrl = `https://api.dicebear.com/7.x/avataaars/png?seed=female${Math.random()}`;
} else if (type === 'celebrity') {
name = celebrityNames[Math.floor(Math.random() * celebrityNames.length)];
// CHANGED: Using .png instead of .svg to fix download distortion
avatarUrl = `https://api.dicebear.com/7.x/initials/png?seed=${name}`;
// Turn on verified badge for celebrities
document.getElementById('verifiedToggle').checked = true;
} else if (type === 'realistic') {
// NEW: Realistic Photos from randomuser.me API - START
try {
const response = await fetch('https://randomuser.me/api/');
const data = await response.json();
const user = data.results[0];
name = user.login.username; // Random user username
avatarUrl = user.picture.large; // High quality picture
} catch (e) {
// Fallback if API fails
name = realisticNames[Math.floor(Math.random() * realisticNames.length)];
const gender = Math.random() > 0.5 ? 'men' : 'women';
const randomNum = Math.floor(Math.random() * 99) + 1;
avatarUrl = `https://randomuser.me/api/portraits/${gender}/${randomNum}.jpg`;
}
// NEW: Realistic Photos from randomuser.me API - END
}
// Select Name and Avatar Based on Type - END
// Show loading state or toast if needed
showToast('Generating identity...', 'info');
// Convert to Base64 - FIXED FOR ALL TYPES
const base64Image = await fetchImageAsBase64(avatarUrl);
if (base64Image) {
// Update Profile Preview and Comment Avatar - START
document.getElementById('profilePreview').src = base64Image;
document.getElementById('commentAvatar').src = base64Image;
// Update Profile Preview and Comment Avatar - END
showToast(`Generated ${type} identity: ${name}`, 'success');
} else {
// Fallback to URL if base64 conversion fails
document.getElementById('profilePreview').src = avatarUrl;
document.getElementById('commentAvatar').src = avatarUrl;
showToast(`Generated identity (standard load): ${name}`, 'warning');
}
// Update Username - START
document.getElementById('username').value = name;
// Update Username - END
// Trigger Preview Update
updatePreview();
}
// ============================================
// RANDOM IDENTITY GENERATOR FUNCTION - END
// ============================================
// ============================================
// MESSAGE STYLE CHANGE FUNCTION - START
// ============================================
function changeMessageStyle(style) {
currentStyle = style;
// Remove active class from all style buttons - START
document.querySelectorAll('.style-btn').forEach(btn => {
btn.classList.remove('active');
});
// Remove active class from all style buttons - END
// Add active class to selected button - START
if (style === 'default') {
document.getElementById('styleDefault').classList.add('active');
} else if (style === 'bubble') {
document.getElementById('styleBubble').classList.add('active');
} else if (style === 'card') {
document.getElementById('styleCard').classList.add('active');
}
// Add active class to selected button - END
// Apply style to preview - START
applyMessageStyle(style);
// Apply style to preview - END
showToast(`Style changed to ${style}`, 'success');
}
function switchPreviewStyle(style) {
currentStyle = style;
// Remove active class from all preview style buttons - START
document.querySelectorAll('.style-switch-btn').forEach(btn => {
btn.classList.remove('active');
});
// Remove active class from all preview style buttons - END
// Add active class to selected button - START
if (style === 'default') {
document.getElementById('previewStyleDefault').classList.add('active');
} else if (style === 'bubble') {
document.getElementById('previewStyleBubble').classList.add('active');
} else if (style === 'card') {
document.getElementById('previewStyleCard').classList.add('active');
}
// Add active class to selected button - END
// Apply style to preview - START
applyMessageStyle(style);
// Apply style to preview - END
}
function applyMessageStyle(style) {
const container = document.getElementById('commentContainer');
// Remove all style classes - START
container.classList.remove('style-bubble', 'style-card');
// Remove all style classes - END
// Add selected style class - START
if (style === 'bubble') {
container.classList.add('style-bubble');
} else if (style === 'card') {
container.classList.add('style-card');
}
// Add selected style class - END
}
// ============================================
// MESSAGE STYLE CHANGE FUNCTION - END
// ============================================
// ============================================
// IMAGE UPLOAD HANDLER - START
// ============================================
function handleImageUpload(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function (e) {
document.getElementById('profilePreview').src = e.target.result;
document.getElementById('commentAvatar').src = e.target.result;
showToast('Profile picture uploaded!', 'success');
};
reader.readAsDataURL(file);
}
}
// ============================================
// IMAGE UPLOAD HANDLER - END
// ============================================
// ============================================
// ADVANCED SECTION TOGGLE - START
// ============================================
function toggleAdvanced() {
const content = document.getElementById('advancedContent');
const arrow = document.getElementById('advancedArrow');
content.classList.toggle('show');
arrow.textContent = content.classList.contains('show') ? '▲' : '▼';
}
// ============================================
// ADVANCED SECTION TOGGLE - END
// ============================================
// ============================================
// BLUR EFFECT FUNCTION - START
// ============================================
function updateBlur() {
const blurValue = document.getElementById('blurSlider').value;
const commentText = document.getElementById('previewText');
commentText.style.filter = `blur(${blurValue}px)`;
document.getElementById('blurValue').textContent = `${blurValue}px`;
}
// ============================================
// BLUR EFFECT FUNCTION - END
// ============================================
// ============================================
// DOWNLOAD IMAGE FUNCTION - START
// ============================================
async function downloadImage() {
const element = document.getElementById('commentContainer');
try {
// Use html2canvas to Capture Element - START
const canvas = await html2canvas(element, {
backgroundColor: null,
scale: 3, // معیار بہتر کیا گیا ہے
useCORS: true, // پروفائل پکچر کو ٹھیک رکھنے کے لیے
allowTaint: false, // یہ لائن تصویر خراب ہونے سے بچائے گی
onclone: (clonedDoc) => {
// یہ حصہ کٹنے والے مسئلے کو حل کرتا ہے
const clonedEl = clonedDoc.getElementById('commentContainer');
if (clonedEl.classList.contains('style-bubble')) {
clonedEl.style.marginLeft = "15px"; // بائیں طرف جگہ بنائی گئی
clonedEl.style.marginRight = "15px";
}
}
});
// Use html2canvas to Capture Element - END
// Create Download Link - START
const link = document.createElement('a');
link.download = 'npriva-comment-' + Date.now() + '.png';
link.href = canvas.toDataURL('image/png');
link.click();
// Create Download Link - END
showToast('Image downloaded successfully!', 'success');
} catch (error) {
showToast('Error generating image', 'error');
console.error(error);
}
}
// ============================================
// DOWNLOAD IMAGE FUNCTION - END
// ============================================
// ============================================
// COPY TO CLIPBOARD FUNCTION - START
// ============================================
async function copyToClipboard() {
const element = document.getElementById('commentContainer');
try {
// Use html2canvas to Capture Element - START
const canvas = await html2canvas(element, {
backgroundColor: null,
scale: 2,
useCORS: true,
allowTaint: true
});
// Use html2canvas to Capture Element - END
// Convert to Blob and Copy - START
canvas.toBlob(async (blob) => {
try {
await navigator.clipboard.write([
new ClipboardItem({ 'image/png': blob })
]);
showToast('Copied to clipboard!', 'success');
} catch (err) {
// Fallback for browsers that don't support clipboard API
showToast('Clipboard access denied. Try downloading instead.', 'error');
}
});
// Convert to Blob and Copy - END
} catch (error) {
showToast('Error copying image', 'error');
console.error(error);
}
}
// ============================================
// COPY TO CLIPBOARD FUNCTION - END
// ============================================
// ============================================
// TOAST NOTIFICATION FUNCTION - START
// ============================================
function showToast(message, type = 'success') {
const toast = document.getElementById('toast');
const toastIcon = document.getElementById('toastIcon');
const toastMessage = document.getElementById('toastMessage');
// Set Toast Content - START
toastMessage.textContent = message;
toastIcon.textContent = type === 'success' ? '✓' : '✕';
toast.className = 'toast ' + type;
// Set Toast Content - END
// Show Toast - START
toast.classList.add('show');
// Show Toast - END
// Hide Toast After 3 Seconds - START
setTimeout(() => {
toast.classList.remove('show');
}, 3000);
// Hide Toast After 3 Seconds - END
}
// ============================================
// TOAST NOTIFICATION FUNCTION - END
// ============================================
// ============================================
// INITIAL PREVIEW UPDATE ON PAGE LOAD - START
// ============================================
document.addEventListener('DOMContentLoaded', function () {
updatePreview();
// Add Right Click / Long Press to Download - START
const previewContainer = document.getElementById('commentContainer');
// Context Menu (Right Click)
previewContainer.addEventListener('contextmenu', function (e) {
e.preventDefault(); // Prevent default browser menu
if (confirm('Do you want to download this image?')) {
downloadImage();
}
});
// Long Press (Mobile)
let pressTimer;
previewContainer.addEventListener('touchstart', function (e) {
pressTimer = setTimeout(function () {
if (confirm('Do you want to download this image?')) {
downloadImage();
}
}, 800); // 800ms long press
});
previewContainer.addEventListener('touchend', function (e) {
clearTimeout(pressTimer);
});
previewContainer.addEventListener('touchmove', function (e) {
clearTimeout(pressTimer);
});
// Add Right Click / Long Press to Download - END
});
// ============================================
// INITIAL PREVIEW UPDATE ON PAGE LOAD - END
// ============================================
</script>
<!-- ============================================
JAVASCRIPT CODE - END
============================================ -->
</body>
</html>