User:Docmoates/Social: Difference between revisions

From XMethod Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 47: Line 47:
.sf-empty-text { font-size: 18px; font-weight: 500; }
.sf-empty-text { font-size: 18px; font-weight: 500; }
.sf-empty-sub { font-size: 14px; margin-top: 8px; color: #8a8d91; }
.sf-empty-sub { font-size: 14px; margin-top: 8px; color: #8a8d91; }
.sf-stories { display: flex; gap: 12px; padding: 16px; background: white; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 20px; }
.sf-stories { display: flex; gap: 12px; padding: 16px; background: white; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 20px; overflow-x: auto; }
.sf-story-item { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 80px; }
.sf-story-ring { width: 68px; height: 68px; border-radius: 50%; padding: 3px; background: linear-gradient(45deg, #f09433, #e6683c, #dc2743, #cc2366, #bc1888); }
.sf-story-ring.no-story { background: #e4e6eb; }
.sf-story-avatar { width: 100%; height: 100%; border-radius: 50%; border: 3px solid white; object-fit: cover; cursor: pointer; background: linear-gradient(135deg, #667eea, #764ba2); display: flex; align-items: center; justify-content: center; color: white; font-weight: 600; font-size: 20px; }
.sf-story-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.sf-story-name { font-size: 12px; color: #65676b; max-width: 80px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sf-create-story { width: 68px; height: 68px; border-radius: 50%; background: #e4e6eb; display: flex; align-items: center; justify-content: center; font-size: 28px; color: #1877f2; cursor: pointer; border: none; }
.sf-create-story { width: 68px; height: 68px; border-radius: 50%; background: #e4e6eb; display: flex; align-items: center; justify-content: center; font-size: 28px; color: #1877f2; cursor: pointer; border: none; }
.sf-modal { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.8); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); z-index: 9999; align-items: center; justify-content: center; }
.sf-modal { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.8); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); z-index: 9999; align-items: center; justify-content: center; }
.sf-modal.active { display: flex; }
.sf-modal.active { display: flex; }
.sf-modal-content { background: white; border-radius: 12px; padding: 24px; max-width: 450px; width: 90%; }
.sf-modal-content { background: white; border-radius: 12px; padding: 24px; max-width: 450px; width: 90%; box-shadow: 0 8px 32px rgba(0,0,0,0.12); }
.sf-modal-title { font-size: 20px; font-weight: 600; margin-bottom: 16px; }
.sf-modal-title { font-size: 20px; font-weight: 600; margin-bottom: 16px; }
.sf-modal-input { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; margin-bottom: 12px; }
.sf-modal-input { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; margin-bottom: 12px; }
Line 83: Line 89:
.sf-emoji-tab { background: none; border: none; font-size: 18px; padding: 6px 10px; cursor: pointer; border-radius: 6px; opacity: 0.5; }
.sf-emoji-tab { background: none; border: none; font-size: 18px; padding: 6px 10px; cursor: pointer; border-radius: 6px; opacity: 0.5; }
.sf-emoji-tab:hover, .sf-emoji-tab.active { opacity: 1; background: #f0f2f5; }
.sf-emoji-tab:hover, .sf-emoji-tab.active { opacity: 1; background: #f0f2f5; }
.sf-story-viewer { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: #000; z-index: 10000; }
.sf-story-viewer.active { display: flex; align-items: center; justify-content: center; }
.sf-story-viewer img { max-width: 100%; max-height: 100%; object-fit: contain; }
.sf-story-close { position: absolute; top: 20px; right: 20px; background: rgba(255,255,255,0.2); border: none; color: white; font-size: 24px; width: 40px; height: 40px; border-radius: 50%; cursor: pointer; }
.sf-story-progress { position: absolute; top: 10px; left: 10px; right: 10px; height: 3px; background: rgba(255,255,255,0.3); border-radius: 2px; }
.sf-story-progress-fill { height: 100%; background: white; border-radius: 2px; animation: storyProgress 5s linear forwards; }
@keyframes storyProgress { from { width: 0%; } to { width: 100%; } }
</style>
</style>


<div class="sf-stories"><div class="sf-story"><button class="sf-create-story" id="add-story-btn">+</button><span style="font-size:12px;margin-top:8px;">Add Story</span></div></div>
<div class="sf-stories" id="stories-container">
<div class="sf-story-item">
<button class="sf-create-story" id="add-story-btn">+</button>
<span class="sf-story-name">Add Story</span>
</div>
</div>


<div class="sf-composer">
<div class="sf-composer">
Line 124: Line 142:
<div class="sf-modal-content">
<div class="sf-modal-content">
<div class="sf-modal-title">Set Profile Photo</div>
<div class="sf-modal-title">Set Profile Photo</div>
<input type="text" class="sf-modal-input" id="profile-url-input" placeholder="Enter image URL...">
<div class="sf-tabs">
<p style="font-size:12px;color:#65676b;margin-bottom:12px;">Upload to wiki first, then paste URL</p>
<div class="sf-tab active" data-ptab="pupload">Upload</div>
<div class="sf-tab" data-ptab="purl">From URL</div>
</div>
<div class="sf-tab-content active" id="tab-pupload">
<div class="sf-upload-zone" id="profile-upload-zone">
<div class="sf-upload-icon">📸</div>
<div class="sf-upload-text">Click to select or drag photo here</div>
<input type="file" id="profile-file-input" accept="image/*" style="display:none">
</div>
<div class="sf-upload-progress" id="profile-upload-progress">
<div class="sf-progress-bar"><div class="sf-progress-fill" id="profile-progress-fill"></div></div>
<p style="font-size:12px;color:#65676b;margin-top:8px;" id="profile-upload-status">Uploading...</p>
</div>
<img class="sf-preview-thumb" id="profile-upload-preview" style="display:none">
</div>
<div class="sf-tab-content" id="tab-purl">
<input type="text" class="sf-modal-input" id="profile-url-input" placeholder="Paste image URL...">
<img class="sf-preview-thumb" id="profile-url-preview" style="display:none">
</div>
<div class="sf-modal-buttons">
<div class="sf-modal-buttons">
<button class="sf-modal-btn sf-modal-btn-cancel" id="profile-cancel-btn">Cancel</button>
<button class="sf-modal-btn sf-modal-btn-cancel" id="profile-cancel-btn">Cancel</button>
<button class="sf-modal-btn sf-modal-btn-save" id="profile-save-btn">Save</button>
<button class="sf-modal-btn sf-modal-btn-save" id="profile-save-btn">Save</button>
</div>
</div>
</div>
<div class="sf-modal" id="story-modal">
<div class="sf-modal-content">
<div class="sf-modal-title">Add Story</div>
<div class="sf-tabs">
<div class="sf-tab active" data-stab="supload">Upload</div>
<div class="sf-tab" data-stab="surl">From URL</div>
</div>
<div class="sf-tab-content active" id="tab-supload">
<div class="sf-upload-zone" id="story-upload-zone">
<div class="sf-upload-icon">📷</div>
<div class="sf-upload-text">Click to select or drag image here</div>
<input type="file" id="story-file-input" accept="image/*" style="display:none">
</div>
<div class="sf-upload-progress" id="story-upload-progress">
<div class="sf-progress-bar"><div class="sf-progress-fill" id="story-progress-fill"></div></div>
<p style="font-size:12px;color:#65676b;margin-top:8px;" id="story-upload-status">Uploading...</p>
</div>
<img class="sf-preview-thumb" id="story-upload-preview" style="display:none">
</div>
<div class="sf-tab-content" id="tab-surl">
<input type="text" class="sf-modal-input" id="story-url-input" placeholder="Paste image URL...">
<img class="sf-preview-thumb" id="story-url-preview" style="display:none">
</div>
<div class="sf-modal-buttons">
<button class="sf-modal-btn sf-modal-btn-cancel" id="story-cancel-btn">Cancel</button>
<button class="sf-modal-btn sf-modal-btn-save" id="story-add-btn">Add Story</button>
</div>
</div>
</div>
</div>
Line 204: Line 270:
</div>
</div>
</div>
</div>
</div>
<div class="sf-story-viewer" id="story-viewer">
<div class="sf-story-progress"><div class="sf-story-progress-fill" id="story-progress-bar"></div></div>
<button class="sf-story-close" id="story-close-btn">✕</button>
<img id="story-viewer-img" src="">
</div>
</div>


Line 212: Line 284:
var csrfToken='';
var csrfToken='';


try{if(window.mw)user=mw.config.get('wgUserName')||'Guest';}catch(e){}
try{if(window.mw){user=mw.config.get('wgUserName');if(!user)user='Guest';}}catch(e){}


var photo=localStorage.getItem('sf_photo_'+user)||'';
var photo=localStorage.getItem('sf_photo_'+user)||'';
Line 225: Line 297:
gestures:['👋','🤚','🖐️','✋','🖖','👌','🤌','🤏','✌️','🤞','🤟','🤘','🤙','👈','👉','👆','👇','☝️','👍','👎','✊','👊','🤛','🤜','👏','🙌','👐','🤲','🤝','🙏','✍️','💪','🦵','🦶','👂','👃','🧠','🫀','🫁','🦷','🦴','👀','👁️','👅','👄'],
gestures:['👋','🤚','🖐️','✋','🖖','👌','🤌','🤏','✌️','🤞','🤟','🤘','🤙','👈','👉','👆','👇','☝️','👍','👎','✊','👊','🤛','🤜','👏','🙌','👐','🤲','🤝','🙏','✍️','💪','🦵','🦶','👂','👃','🧠','🫀','🫁','🦷','🦴','👀','👁️','👅','👄'],
animals:['🐶','🐱','🐭','🐹','🐰','🦊','🐻','🐼','🐨','🐯','🦁','🐮','🐷','🐸','🐵','🐔','🐧','🐦','🐤','🦆','🦅','🦉','🦇','🐺','🐗','🐴','🦄','🐝','🐛','🦋','🐌','🐞','🐜','🦟','🐢','🐍','🦎','🦂','🦀','🦑','🐙','🦐','🐠','🐟','🐬','🐳','🦈','🐊','🐅','🐆','🦓','🦍','🐘','🦛','🦏'],
animals:['🐶','🐱','🐭','🐹','🐰','🦊','🐻','🐼','🐨','🐯','🦁','🐮','🐷','🐸','🐵','🐔','🐧','🐦','🐤','🦆','🦅','🦉','🦇','🐺','🐗','🐴','🦄','🐝','🐛','🦋','🐌','🐞','🐜','🦟','🐢','🐍','🦎','🦂','🦀','🦑','🐙','🦐','🐠','🐟','🐬','🐳','🦈','🐊','🐅','🐆','🦓','🦍','🐘','🦛','🦏'],
food:['🍎','🍊','🍋','🍌','🍉','🍇','🍓','🫐','🍈','🍒','🍑','🥭','🍍','🥥','🥝','🍅','🥑','🥦','🥬','🥒','🌶️','🫑','🌽','🥕','🫒','🧄','🧅','🥔','🍠','🥐','🥯','🍞','🥖','🥨','🧀','🥚','🍳','🧈','🥞','🧇','🥓','🥩','🍗','🍖','🦴','🌭','🍔','🍟','🍕','🫓','🥪','🥙','🧆','🌮','🌯','🫔','🥗','🥘','🫕','🥫','🍝','🍜','🍲','🍛','🍣','🍱','🥟','🦪','🍤','🍙','🍚','🍘','🍥','🥠','🥮','🍢','🍡','🍧','🍨','🍦','🥧','🧁','🍰','🎂','🍮','🍭','🍬','🍫','🍿','🍩','🍪'],
food:['🍎','🍊','🍋','🍌','🍉','🍇','🍓','🫐','🍈','🍒','🍑','🥭','🍍','🥥','🥝','🍅','🥑','🥦','🥬','🥒','🌶️','🫑','🌽','🥕','🫒','🧄','🧅','🥔','🍠','🥐','🥯','🍞','🥖','🥨','🧀','🥚','🍳','🧈','🥞','🧇','🥓','🥩','🍗','🍖','🌭','🍔','🍟','🍕','🥪','🥙','🌮','🌯','🥗','🍝','🍜','🍲','🍛','🍣','🍱','🥟','🍤','🍙','🍚','🍘','🍥','🍢','🍡','🍧','🍨','🍦','🥧','🧁','🍰','🎂','🍮','🍭','🍬','🍫','🍿','🍩','🍪'],
activities:['⚽','🏀','🏈','⚾','🥎','🎾','🏐','🏉','🥏','🎱','🪀','🏓','🏸','🏒','🏑','🥍','🏏','🪃','🥅','⛳','🪁','🏹','🎣','🤿','🥊','🥋','🎽','🛹','🛼','🛷','⛸️','🥌','🎿','⛷️','🏂','🪂','🏋️','🤼','🤸','🤺','⛹️','🤾','🏌️','🏇','🧘','🏄','🏊','🤽','🚣','🧗','🚴','🚵','🎖️','🏆','🥇','🥈','🥉','🏅','🎪','🤹','🎭','🎨','🎬','🎤','🎧','🎼','🎹','🥁','🪘','🎷','🎺','🪗','🎸','🪕','🎻','🎲','♟️','🎯','🎳','🎮','🎰'],
activities:['⚽','🏀','🏈','⚾','🥎','🎾','🏐','🏉','🥏','🎱','🏓','🏸','🏒','🏑','🥍','🏏','🥅','⛳','🏹','🎣','🥊','🥋','🎽','🛹','🛷','⛸️','🥌','🎿','⛷️','🏂','🏋️','🤼','🤸','🤺','⛹️','🤾','🏌️','🏇','🧘','🏄','🏊','🤽','🚣','🧗','🚴','🚵','🎖️','🏆','🥇','🥈','🥉','🏅','🎪','🤹','🎭','🎨','🎬','🎤','🎧','🎼','🎹','🥁','🎷','🎺','🎸','🎻','🎲','♟️','🎯','🎳','🎮','🎰'],
objects:['💡','🔦','🕯️','🪔','📱','💻','🖥️','🖨️','⌨️','🖱️','💾','💿','📀','📷','📸','📹','🎥','📽️','🎞️','📞','☎️','📟','📠','📺','📻','🎙️','🎚️','🎛️','🧭','⏱️','⏲️','⏰','🕰️','⌛','⏳','📡','🔋','🔌','💰','💵','💴','💶','💷','🪙','💳','💎','⚖️','🪜','🧰','🪛','🔧','🔨','⚒️','🛠️','⛏️','🪚','🔩','⚙️','🪤','🧱','⛓️','🧲','🔫','💣','🧨','🪓','🔪','🗡️','⚔️','🛡️','🚬','⚰️','🪦','⚱️','🏺','🔮','📿','🧿','💈','⚗️','🔭','🔬','🕳️','🩹','🩺','💊','💉','🩸','🧬','🦠','🧫','🧪','🌡️','🧹','🧺','🧻','🚽','🚿','🛁','🛀','🧼','🪥','🪒','🧽','🪣','🧴','🛎️','🔑','🗝️','🚪','🪑','🛋️','🛏️','🛌','🧸','🖼️','🪞','🪟','🛍️','🛒','🎁','🎈','🎏','🎀','🪄','🪅','🎊','🎉','🎎','🏮','🎐','🧧','✉️','📩','📨','📧','💌','📥','📤','📦','🏷️','📪','📫','📬','📭','📮','📯','📜','📃','📄','📑','🧾','📊','📈','📉','🗒️','🗓️','📆','📅','🗑️','📇','🗃️','🗳️','🗄️','📋','📁','📂','🗂️','🗞️','📰','📓','📔','📒','📕','📗','📘','📙','📚','📖','🔖','🧷','🔗','📎','🖇️','📐','📏','🧮','📌','📍','✂️','🖊️','🖋️','✒️','🖌️','🖍️','📝','✏️','🔍','🔎','🔏','🔐','🔒','🔓'],
objects:['💡','🔦','🕯️','📱','💻','🖥️','🖨️','⌨️','🖱️','💾','💿','📀','📷','📸','📹','🎥','📽️','📞','☎️','📟','📠','📺','📻','🎙️','🎚️','🎛️','🧭','⏱️','⏲️','⏰','🕰️','⌛','⏳','📡','🔋','🔌','💰','💵','💴','💶','💷','💳','💎','⚖️','🧰','🔧','🔨','🛠️','⛏️','🔩','⚙️','🧱','🔫','💣','🔪','🗡️','⚔️','🛡️','🚬','⚰️','⚱️','🏺','🔮','📿','🧿','💈','⚗️','🔭','🔬','🕳️','🩹','🩺','💊','💉','🧬','🦠','🧫','🧪','🌡️','🧹','🧺','🧻','🚽','🚿','🛁','🧼','🧽','🧴','🛎️','🔑','🗝️','🚪','🛋️','🛏️','🧸','🖼️','🛍️','🛒','🎁','🎈','🎏','🎀','🎊','🎉','🎎','🏮','🎐','🧧','✉️','📩','📨','📧','💌','📥','📤','📦','🏷️','📪','📫','📬','📭','📮','📯','📜','📃','📄','📑','🧾','📊','📈','📉','📆','📅','🗑️','📋','📁','📂','📰','📓','📔','📒','📕','📗','📘','📙','📚','📖','🔖','🔗','📎','📐','📏','🧮','📌','📍','✂️','🖊️','🖋️','✒️','🖌️','🖍️','📝','✏️','🔍','🔎','🔏','🔐','🔒','🔓'],
symbols:['❤️','🧡','💛','💚','💙','💜','🖤','🤍','🤎','💔','❣️','💕','💞','💓','💗','💖','💘','💝','💟','☮️','✝️','☪️','🕉️','☸️','✡️','🔯','🕎','☯️','☦️','🛐','','','','','','','','','','','','','','🆔','⚛️','🉑','☢️','☣️','📴','📳','🈶','🈚','🈸','🈺','🈷️','✴️','🆚','💮','🉐','㊙️','㊗️','🈴','🈵','🈹','🈲','🅰️','🅱️','🆎','🆑','🅾️','🆘','','','🛑','','📛','🚫','💯','💢','♨️','🚷','🚯','🚳','🚱','🔞','📵','🚭','','','','','‼️','⁉️','🔅','🔆','〽️','⚠️','🚸','🔱','⚜️','🔰','♻️','','🈯','💹','❇️','✳️','','🌐','💠','Ⓜ️','🌀','💤','🏧','🚾','','🅿️','🛗','🈳','🈂️','🛂','🛃','🛄','🛅','🚹','🚺','🚼','⚧️','🚻','🚮','🎦','📶','🈁','🔣','ℹ️','🔤','🔡','🔠','🆖','🆗','🆙','🆒','🆕','🆓','0️⃣','1️⃣','2️⃣','3️⃣','4️⃣','5️⃣','6️⃣','7️⃣','8️⃣','9️⃣','🔟','🔢','#️⃣','*️⃣','⏏️','▶️','⏸️','⏯️','⏹️','⏺️','⏭️','⏮️','','','','','◀️','🔼','🔽','➡️','⬅️','⬆️','⬇️','↗️','↘️','↙️','↖️','↕️','↔️','↪️','↩️','⤴️','⤵️','🔀','🔁','🔂','🔄','🔃','🎵','🎶','','','','✖️','🟰','♾️','💲','💱','™️','©️','®️','〰️','','','🔚','🔙','🔛','🔝','🔜','✔️','☑️','🔘','🔴','🟠','🟡','🟢','🔵','🟣','','','🟤','🔺','🔻','🔸','🔹','🔶','🔷','🔳','🔲','▪️','▫️','','','◼️','◻️','🟥','🟧','🟨','🟩','🟦','🟪','⬛','⬜','🟫','🔈','🔇','🔉','🔊','🔔','🔕','📣','📢','👁️‍🗨️','💬','💭','🗯️','♠️','♣️','♥️','♦️','🃏','🎴','🀄','🕐','🕑','🕒','🕓','🕔','🕕','🕖','🕗','🕘','🕙','🕚','🕛','🕜','🕝','🕞','🕟','🕠','🕡','🕢','🕣','🕤','🕥','🕦','🕧']
symbols:['❤️','🧡','💛','💚','💙','💜','🖤','🤍','🤎','💔','❣️','💕','💞','💓','💗','💖','💘','💝','💟','☮️','✝️','☪️','🕉️','☸️','✡️','🔯','🕎','☯️','☦️','🛐','','','','','','','','','','','','','','🆔','⚛️','☢️','☣️','📴','📳','✴️','🆚','💮','㊙️','㊗️','🅰️','🅱️','🆎','🆑','🅾️','🆘','','','🛑','','📛','🚫','💯','💢','♨️','🚷','🚯','🚳','🚱','🔞','📵','🚭','','','','','‼️','⁉️','🔅','🔆','〽️','⚠️','🚸','🔱','⚜️','🔰','♻️','','💹','❇️','✳️','','🌐','💠','Ⓜ️','🌀','💤','🏧','🚾','','🅿️','🈳','🈂️','🛂','🛃','🛄','🛅','🚹','🚺','🚼','⚧️','🚻','🚮','🎦','📶','🔣','ℹ️','🔤','🔡','🔠','🆖','🆗','🆙','🆒','🆕','🆓','0️⃣','1️⃣','2️⃣','3️⃣','4️⃣','5️⃣','6️⃣','7️⃣','8️⃣','9️⃣','🔟','🔢','#️⃣','*️⃣','⏏️','▶️','⏸️','⏯️','⏹️','⏺️','⏭️','⏮️','','','','','◀️','🔼','🔽','➡️','⬅️','⬆️','⬇️','↗️','↘️','↙️','↖️','↕️','↔️','↪️','↩️','⤴️','⤵️','🔀','🔁','🔂','🔄','🔃','🎵','🎶','','','','✖️','🟰','♾️','💲','💱','™️','©️','®️','〰️','','','🔚','🔙','🔛','🔝','🔜','✔️','☑️','🔘','🔴','🟠','🟡','🟢','🔵','🟣','','','🟤','🔺','🔻','🔸','🔹','🔶','🔷','🔳','🔲','▪️','▫️','','','◼️','◻️','🟥','🟧','🟨','🟩','🟦','🟪','','','🟫','🔈','🔇','🔉','🔊','🔔','🔕','📣','📢','💬','💭','🗯️','♠️','♣️','♥️','♦️','🃏','🎴','🀄']
};
};


Line 253: Line 325:
csrfToken=d.query.tokens.csrftoken;
csrfToken=d.query.tokens.csrftoken;
return csrfToken;
return csrfToken;
});
}
function uploadFile(file,prefix,onProgress,onDone,onError){
getToken().then(function(token){
var filename=prefix+'_'+user+'_'+Date.now()+'.'+file.name.split('.').pop();
var formData=new FormData();
formData.append('action','upload');
formData.append('filename',filename);
formData.append('file',file);
formData.append('token',token);
formData.append('format','json');
formData.append('ignorewarnings','1');
var xhr=new XMLHttpRequest();
xhr.open('POST',apiBase,true);
xhr.withCredentials=true;
xhr.upload.onprogress=function(e){if(e.lengthComputable)onProgress(Math.round((e.loaded/e.total)*100));};
xhr.onload=function(){
if(xhr.status===200){
var resp=JSON.parse(xhr.responseText);
if(resp.upload){
if(resp.upload.imageinfo){onDone(resp.upload.imageinfo.url);}
else if(resp.upload.warnings){onError('Warning: '+JSON.stringify(resp.upload.warnings));}
else{onError('Upload issue');}
}else if(resp.error){onError(resp.error.info);}
else{onError('Unknown error');}
}else{onError('Upload failed');}
};
xhr.onerror=function(){onError('Upload failed');};
xhr.send(formData);
});
});
}
}
Line 265: Line 368:
var postContent=gel('post-content');
var postContent=gel('post-content');
if(postContent)postContent.placeholder='What is on your mind, '+user+'?';
if(postContent)postContent.placeholder='What is on your mind, '+user+'?';
// Profile modal tabs
var uploadedProfileFile=null;
document.querySelectorAll('[data-ptab]').forEach(function(tab){
tab.addEventListener('click',function(){
document.querySelectorAll('[data-ptab]').forEach(function(t){t.classList.remove('active');});
document.querySelectorAll('#profile-modal .sf-tab-content').forEach(function(c){c.classList.remove('active');});
tab.classList.add('active');
gel('tab-'+tab.dataset.ptab).classList.add('active');
});
});


gel('composer-avatar').addEventListener('click',function(){
gel('composer-avatar').addEventListener('click',function(){
gel('profile-url-input').value=photo;
gel('profile-url-input').value=photo;
gel('profile-upload-preview').style.display='none';
gel('profile-url-preview').style.display='none';
gel('profile-upload-progress').style.display='none';
uploadedProfileFile=null;
gel('profile-modal').classList.add('active');
gel('profile-modal').classList.add('active');
});
});
gel('profile-cancel-btn').addEventListener('click',function(){gel('profile-modal').classList.remove('active');});
gel('profile-cancel-btn').addEventListener('click',function(){gel('profile-modal').classList.remove('active');});
var profileUploadZone=gel('profile-upload-zone');
var profileFileInput=gel('profile-file-input');
profileUploadZone.addEventListener('click',function(){profileFileInput.click();});
profileUploadZone.addEventListener('dragover',function(e){e.preventDefault();profileUploadZone.classList.add('dragover');});
profileUploadZone.addEventListener('dragleave',function(){profileUploadZone.classList.remove('dragover');});
profileUploadZone.addEventListener('drop',function(e){
e.preventDefault();
profileUploadZone.classList.remove('dragover');
if(e.dataTransfer.files.length>0)handleProfileFile(e.dataTransfer.files[0]);
});
profileFileInput.addEventListener('change',function(){
if(profileFileInput.files.length>0)handleProfileFile(profileFileInput.files[0]);
});
function handleProfileFile(file){
if(!file.type.startsWith('image/')){alert('Please select an image file');return;}
uploadedProfileFile=file;
var reader=new FileReader();
reader.onload=function(e){
gel('profile-upload-preview').src=e.target.result;
gel('profile-upload-preview').style.display='block';
};
reader.readAsDataURL(file);
}
gel('profile-url-input').addEventListener('input',function(){
var url=this.value.trim();
if(url){
gel('profile-url-preview').src=url;
gel('profile-url-preview').style.display='block';
}else{
gel('profile-url-preview').style.display='none';
}
});
gel('profile-save-btn').addEventListener('click',function(){
gel('profile-save-btn').addEventListener('click',function(){
var activeTab=document.querySelector('[data-ptab].active').dataset.ptab;
if(activeTab==='purl'){
photo=gel('profile-url-input').value.trim();
photo=gel('profile-url-input').value.trim();
localStorage.setItem('sf_photo_'+user,photo);
localStorage.setItem('sf_photo_'+user,photo);
setAv();
setAv();
gel('profile-modal').classList.remove('active');
gel('profile-modal').classList.remove('active');
}else{
if(uploadedProfileFile){
gel('profile-upload-progress').style.display='block';
gel('profile-progress-fill').style.width='10%';
gel('profile-upload-status').textContent='Uploading...';
uploadFile(uploadedProfileFile,'ProfilePhoto',function(pct){
gel('profile-progress-fill').style.width=pct+'%';
},function(url){
gel('profile-progress-fill').style.width='100%';
gel('profile-upload-status').textContent='Done!';
photo=url;
localStorage.setItem('sf_photo_'+user,photo);
setAv();
setTimeout(function(){gel('profile-modal').classList.remove('active');},500);
},function(err){
gel('profile-upload-status').textContent='Error: '+err;
});
}else{
alert('Please select an image to upload');
}
}
});
// Story modal tabs
var uploadedStoryFile=null;
document.querySelectorAll('[data-stab]').forEach(function(tab){
tab.addEventListener('click',function(){
document.querySelectorAll('[data-stab]').forEach(function(t){t.classList.remove('active');});
document.querySelectorAll('#story-modal .sf-tab-content').forEach(function(c){c.classList.remove('active');});
tab.classList.add('active');
gel('tab-'+tab.dataset.stab).classList.add('active');
});
});
});
gel('add-story-btn').addEventListener('click',function(){
gel('story-url-input').value='';
gel('story-upload-preview').style.display='none';
gel('story-url-preview').style.display='none';
gel('story-upload-progress').style.display='none';
uploadedStoryFile=null;
gel('story-modal').classList.add('active');
});
gel('story-cancel-btn').addEventListener('click',function(){gel('story-modal').classList.remove('active');});
var storyUploadZone=gel('story-upload-zone');
var storyFileInput=gel('story-file-input');
storyUploadZone.addEventListener('click',function(){storyFileInput.click();});
storyUploadZone.addEventListener('dragover',function(e){e.preventDefault();storyUploadZone.classList.add('dragover');});
storyUploadZone.addEventListener('dragleave',function(){storyUploadZone.classList.remove('dragover');});
storyUploadZone.addEventListener('drop',function(e){
e.preventDefault();
storyUploadZone.classList.remove('dragover');
if(e.dataTransfer.files.length>0)handleStoryFile(e.dataTransfer.files[0]);
});
storyFileInput.addEventListener('change',function(){
if(storyFileInput.files.length>0)handleStoryFile(storyFileInput.files[0]);
});
function handleStoryFile(file){
if(!file.type.startsWith('image/')){alert('Please select an image file');return;}
uploadedStoryFile=file;
var reader=new FileReader();
reader.onload=function(e){
gel('story-upload-preview').src=e.target.result;
gel('story-upload-preview').style.display='block';
};
reader.readAsDataURL(file);
}
gel('story-url-input').addEventListener('input',function(){
var url=this.value.trim();
if(url){
gel('story-url-preview').src=url;
gel('story-url-preview').style.display='block';
}else{
gel('story-url-preview').style.display='none';
}
});
gel('story-add-btn').addEventListener('click',function(){
var activeTab=document.querySelector('[data-stab].active').dataset.stab;
if(activeTab==='surl'){
var url=gel('story-url-input').value.trim();
if(url){
createStory(url);
}else{
alert('Please enter an image URL');
}
}else{
if(uploadedStoryFile){
gel('story-upload-progress').style.display='block';
gel('story-progress-fill').style.width='10%';
gel('story-upload-status').textContent='Uploading...';
uploadFile(uploadedStoryFile,'Story',function(pct){
gel('story-progress-fill').style.width=pct+'%';
},function(url){
gel('story-progress-fill').style.width='100%';
gel('story-upload-status').textContent='Done!';
setTimeout(function(){
gel('story-modal').classList.remove('active');
createStory(url);
},500);
},function(err){
gel('story-upload-status').textContent='Error: '+err;
});
}else{
alert('Please select an image to upload');
}
}
});
function createStory(imageUrl){
getToken().then(function(token){
return apiPost({action:'socialfeed',sfaction:'createstory',image_url:imageUrl,token:token});
}).then(function(d){
if(d.error){alert('Error: '+d.error.info);return;}
loadStories();
gel('story-modal').classList.remove('active');
}).catch(function(e){alert('Error creating story');});
}
function loadStories(){
apiGet({action:'socialfeed',sfaction:'getstories'}).then(function(d){
renderStories((d.socialfeed?d.socialfeed.stories:[])||[]);
}).catch(function(){});
}
function renderStories(stories){
var container=gel('stories-container');
var h='<div class="sf-story-item"><button class="sf-create-story" id="add-story-btn">+</button><span class="sf-story-name">Add Story</span></div>';
stories.forEach(function(s){
var pic=localStorage.getItem('sf_photo_'+s.username)||'';
var av=pic?'<img src="'+pic+'">':init(s.username);
h+='<div class="sf-story-item"><div class="sf-story-ring"><div class="sf-story-avatar" data-story="'+s.image_url+'">'+av+'</div></div><span class="sf-story-name">'+esc(s.username)+'</span></div>';
});
container.innerHTML=h;
gel('add-story-btn').addEventListener('click',function(){
gel('story-url-input').value='';
gel('story-upload-preview').style.display='none';
gel('story-url-preview').style.display='none';
gel('story-upload-progress').style.display='none';
uploadedStoryFile=null;
gel('story-modal').classList.add('active');
});
container.querySelectorAll('[data-story]').forEach(function(el){
el.addEventListener('click',function(){
gel('story-viewer-img').src=el.dataset.story;
gel('story-viewer').classList.add('active');
gel('story-progress-bar').style.animation='none';
setTimeout(function(){gel('story-progress-bar').style.animation='storyProgress 5s linear forwards';},10);
setTimeout(function(){gel('story-viewer').classList.remove('active');},5000);
});
});
}
gel('story-close-btn').addEventListener('click',function(){gel('story-viewer').classList.remove('active');});
gel('story-viewer').addEventListener('click',function(e){if(e.target===this)this.classList.remove('active');});


// Emoji picker
// Emoji picker
Line 360: Line 674:
gel('video-upload-preview').src=url;
gel('video-upload-preview').src=url;
gel('video-upload-preview').style.display='block';
gel('video-upload-preview').style.display='block';
}
function uploadVideo(file){
gel('video-upload-progress').style.display='block';
gel('video-progress-fill').style.width='10%';
gel('video-upload-status').textContent='Preparing upload...';
var filename='SocialVideo_'+user+'_'+Date.now()+'.'+file.name.split('.').pop();
getToken().then(function(token){
gel('video-progress-fill').style.width='30%';
gel('video-upload-status').textContent='Uploading to wiki...';
var formData=new FormData();
formData.append('action','upload');
formData.append('filename',filename);
formData.append('file',file);
formData.append('token',token);
formData.append('format','json');
formData.append('ignorewarnings','1');
var xhr=new XMLHttpRequest();
xhr.open('POST',apiBase,true);
xhr.withCredentials=true;
xhr.upload.onprogress=function(e){
if(e.lengthComputable){
var pct=30+Math.round((e.loaded/e.total)*60);
gel('video-progress-fill').style.width=pct+'%';
}
};
xhr.onload=function(){
if(xhr.status===200){
var resp=JSON.parse(xhr.responseText);
if(resp.upload){
if(resp.upload.imageinfo){
gel('video-progress-fill').style.width='100%';
gel('video-upload-status').textContent='Upload complete!';
pendingVideo=resp.upload.imageinfo.url;
pendingImg='';
mediaType='video';
gel('preview-img').style.display='none';
gel('preview-video').src=pendingVideo;
gel('preview-video').style.display='block';
gel('image-preview').style.display='block';
setTimeout(function(){gel('video-modal').classList.remove('active');},500);
}else if(resp.upload.warnings){
gel('video-upload-status').textContent='Warning: '+JSON.stringify(resp.upload.warnings);
}
}else if(resp.error){
gel('video-upload-status').textContent='Error: '+resp.error.info;
}
}else{
gel('video-upload-status').textContent='Upload failed';
}
};
xhr.onerror=function(){gel('video-upload-status').textContent='Upload failed';};
xhr.send(formData);
});
}
}


Line 446: Line 700:
}else{
}else{
if(uploadedVideoFile){
if(uploadedVideoFile){
uploadVideo(uploadedVideoFile);
gel('video-upload-progress').style.display='block';
gel('video-progress-fill').style.width='10%';
gel('video-upload-status').textContent='Uploading...';
uploadFile(uploadedVideoFile,'SocialVideo',function(pct){
gel('video-progress-fill').style.width=pct+'%';
},function(url){
gel('video-progress-fill').style.width='100%';
gel('video-upload-status').textContent='Done!';
pendingVideo=url;
pendingImg='';
mediaType='video';
gel('preview-img').style.display='none';
gel('preview-video').src=url;
gel('preview-video').style.display='block';
gel('image-preview').style.display='block';
setTimeout(function(){gel('video-modal').classList.remove('active');},500);
},function(err){
gel('video-upload-status').textContent='Error: '+err;
});
}else{
}else{
alert('Please select a video to upload');
alert('Please select a video to upload');
Line 498: Line 770:


// Image modal tabs
// Image modal tabs
document.querySelectorAll('.sf-tab').forEach(function(tab){
document.querySelectorAll('[data-tab]').forEach(function(tab){
tab.addEventListener('click',function(){
tab.addEventListener('click',function(){
document.querySelectorAll('.sf-tab').forEach(function(t){t.classList.remove('active');});
document.querySelectorAll('[data-tab]').forEach(function(t){t.classList.remove('active');});
document.querySelectorAll('.sf-tab-content').forEach(function(c){c.classList.remove('active');});
document.querySelectorAll('#image-modal .sf-tab-content').forEach(function(c){c.classList.remove('active');});
tab.classList.add('active');
tab.classList.add('active');
gel('tab-'+tab.dataset.tab).classList.add('active');
gel('tab-'+tab.dataset.tab).classList.add('active');
Line 556: Line 828:


gel('image-add-btn').addEventListener('click',function(){
gel('image-add-btn').addEventListener('click',function(){
var activeTab=document.querySelector('.sf-tab.active').dataset.tab;
var activeTab=document.querySelector('[data-tab].active').dataset.tab;
if(activeTab==='url'){
if(activeTab==='url'){
var url=gel('image-url-input').value.trim();
var url=gel('image-url-input').value.trim();
Line 573: Line 845:
}else{
}else{
if(uploadedFile){
if(uploadedFile){
uploadImage(uploadedFile);
}else{
alert('Please select an image to upload');
}
}
});
function uploadImage(file){
gel('upload-progress').style.display='block';
gel('upload-progress').style.display='block';
gel('progress-fill').style.width='10%';
gel('progress-fill').style.width='10%';
gel('upload-status').textContent='Preparing upload...';
gel('upload-status').textContent='Uploading...';
 
uploadFile(uploadedFile,'SocialFeed',function(pct){
var filename='SocialFeed_'+user+'_'+Date.now()+'.'+file.name.split('.').pop();
 
getToken().then(function(token){
gel('progress-fill').style.width='30%';
gel('upload-status').textContent='Uploading to wiki...';
 
var formData=new FormData();
formData.append('action','upload');
formData.append('filename',filename);
formData.append('file',file);
formData.append('token',token);
formData.append('format','json');
formData.append('ignorewarnings','1');
 
var xhr=new XMLHttpRequest();
xhr.open('POST',apiBase,true);
xhr.withCredentials=true;
 
xhr.upload.onprogress=function(e){
if(e.lengthComputable){
var pct=30+Math.round((e.loaded/e.total)*60);
gel('progress-fill').style.width=pct+'%';
gel('progress-fill').style.width=pct+'%';
}
},function(url){
};
 
xhr.onload=function(){
if(xhr.status===200){
var resp=JSON.parse(xhr.responseText);
if(resp.upload){
if(resp.upload.imageinfo){
gel('progress-fill').style.width='100%';
gel('progress-fill').style.width='100%';
gel('upload-status').textContent='Upload complete!';
gel('upload-status').textContent='Done!';
pendingImg=resp.upload.imageinfo.url;
pendingImg=url;
pendingVideo='';
pendingVideo='';
mediaType='image';
mediaType='image';
gel('preview-img').src=pendingImg;
gel('preview-img').src=url;
gel('preview-img').style.display='block';
gel('preview-img').style.display='block';
gel('preview-video').style.display='none';
gel('preview-video').style.display='none';
gel('image-preview').style.display='block';
gel('image-preview').style.display='block';
setTimeout(function(){gel('image-modal').classList.remove('active');},500);
setTimeout(function(){gel('image-modal').classList.remove('active');},500);
}else if(resp.upload.warnings){
},function(err){
gel('upload-status').textContent='Warning: '+JSON.stringify(resp.upload.warnings);
gel('upload-status').textContent='Error: '+err;
});
}else{
alert('Please select an image to upload');
}
}
}else if(resp.error){
gel('upload-status').textContent='Error: '+resp.error.info;
}
}
}else{
gel('upload-status').textContent='Upload failed';
}
};
xhr.onerror=function(){gel('upload-status').textContent='Upload failed';};
xhr.send(formData);
});
});
}


gel('remove-image-btn').addEventListener('click',function(){
gel('remove-image-btn').addEventListener('click',function(){
Line 671: Line 901:
apiGet({action:'socialfeed',sfaction:'getposts',limit:20}).then(function(d){
apiGet({action:'socialfeed',sfaction:'getposts',limit:20}).then(function(d){
if(d.socialfeed)render(d.socialfeed.posts||[]);
if(d.socialfeed)render(d.socialfeed.posts||[]);
}).catch(function(){
else render([]);
gel('timeline-container').innerHTML='<div class="sf-empty"><div class="sf-empty-icon">😕</div><div class="sf-empty-text">Error loading</div></div>';
}).catch(function(err){
console.log('Load error:',err);
gel('timeline-container').innerHTML='<div class="sf-empty"><div class="sf-empty-icon">📝</div><div class="sf-empty-text">No posts yet</div><div class="sf-empty-sub">Be the first to share something!</div></div>';
});
});
}
}
Line 724: Line 956:


load();
load();
loadStories();
});
});
</script>
</script>
</div>
</div>
</html>
</html>

Revision as of 03:10, 3 February 2026

Add Story
?
Edit
📍
📝
No posts yet
Be the first to share something!
Set Profile Photo
Upload
From URL
📸
Click to select or drag photo here

Uploading...

Add Story
Upload
From URL
📷
Click to select or drag image here

Uploading...

Add Photo
Upload
From URL
📤
Click to select or drag image here

Uploading...

Add Video
Upload
From URL
🎬
Click to select or drag video here

Uploading...

Supports YouTube, Vimeo, or direct video URLs

Add Location

— or —