User:Docmoates/Social: Difference between revisions

From XMethod Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 3: Line 3:
<style>
<style>
#social-feed-app * { box-sizing: border-box; }
#social-feed-app * { box-sizing: border-box; }
#social-feed-app {
#social-feed-app { max-width: 680px; margin: 0 auto; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif; background: #f0f2f5; min-height: 100vh; padding: 20px; }
    max-width: 680px;
.sf-composer { background: white; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 20px; }
    margin: 0 auto;
.sf-composer-main { display: flex; padding: 16px 20px; gap: 12px; }
    font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif;
.sf-avatar { width: 48px; height: 48px; border-radius: 50%; background: linear-gradient(135deg, #667eea, #764ba2); display: flex; align-items: center; justify-content: center; color: white; font-weight: 600; font-size: 18px; cursor: pointer; position: relative; overflow: hidden; flex-shrink: 0; }
    background: #f0f2f5;
.sf-avatar img { width: 100%; height: 100%; object-fit: cover; }
    min-height: 100vh;
    padding: 20px;
}
.sf-composer {
    background: white;
    border-radius: 12px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    margin-bottom: 20px;
    overflow: hidden;
}
.sf-composer-main {
    display: flex;
    padding: 16px 20px;
    gap: 12px;
}
.sf-avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-weight: 600;
    font-size: 18px;
    flex-shrink: 0;
    cursor: pointer;
    position: relative;
    overflow: hidden;
}
.sf-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
}
.sf-avatar-small { width: 36px; height: 36px; font-size: 14px; }
.sf-avatar-small { width: 36px; height: 36px; font-size: 14px; }
.sf-avatar-edit {
.sf-avatar-edit { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(0,0,0,0.6); color: white; font-size: 10px; padding: 2px; text-align: center; opacity: 0; transition: 0.2s; }
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: rgba(0,0,0,0.6);
    color: white;
    font-size: 10px;
    padding: 2px;
    text-align: center;
    opacity: 0;
    transition: opacity 0.2s;
}
.sf-avatar:hover .sf-avatar-edit { opacity: 1; }
.sf-avatar:hover .sf-avatar-edit { opacity: 1; }
.sf-composer-input {
.sf-composer-input { flex: 1; background: #f0f2f5; border: none; border-radius: 20px; padding: 14px 20px; font-size: 17px; resize: none; min-height: 80px; outline: none; font-family: inherit; }
    flex: 1;
.sf-composer-actions { display: flex; align-items: center; justify-content: space-between; padding: 12px 20px; border-top: 1px solid #e4e6eb; gap: 12px; }
    background: #f0f2f5;
    border: none;
    border-radius: 20px;
    padding: 14px 20px;
    font-size: 17px;
    resize: none;
    min-height: 80px;
    outline: none;
    color: #050505;
    font-family: inherit;
}
.sf-composer-input::placeholder { color: #65676b; }
.sf-composer-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 20px;
    border-top: 1px solid #e4e6eb;
    gap: 12px;
}
.sf-action-buttons { display: flex; gap: 8px; }
.sf-action-buttons { display: flex; gap: 8px; }
.sf-action-btn {
.sf-action-btn { width: 40px; height: 40px; border-radius: 8px; border: none; background: #f0f2f5; cursor: pointer; font-size: 18px; }
    width: 40px;
    height: 40px;
    border-radius: 8px;
    border: none;
    background: #f0f2f5;
    cursor: pointer;
    font-size: 18px;
}
.sf-action-btn:hover { background: #e4e6eb; }
.sf-action-btn:hover { background: #e4e6eb; }
.sf-post-btn {
.sf-post-btn { background: linear-gradient(135deg, #1877f2, #0d65d9); color: white; border: none; border-radius: 8px; padding: 10px 24px; font-size: 15px; font-weight: 600; cursor: pointer; }
    background: linear-gradient(135deg, #1877f2 0%, #0d65d9 100%);
    color: white;
    border: none;
    border-radius: 8px;
    padding: 10px 24px;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
}
.sf-post-btn:disabled { opacity: 0.5; }
.sf-post-btn:disabled { opacity: 0.5; }
.sf-post {
.sf-post { background: white; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 16px; }
    background: white;
.sf-post-header { display: flex; align-items: center; padding: 16px; gap: 12px; }
    border-radius: 12px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    margin-bottom: 16px;
}
.sf-post-header {
    display: flex;
    align-items: center;
    padding: 16px;
    gap: 12px;
}
.sf-post-user-info { flex: 1; }
.sf-post-user-info { flex: 1; }
.sf-post-username { font-weight: 600; color: #050505; font-size: 15px; }
.sf-post-username { font-weight: 600; font-size: 15px; }
.sf-post-meta { font-size: 13px; color: #65676b; }
.sf-post-meta { font-size: 13px; color: #65676b; }
.sf-post-menu { background: none; border: none; font-size: 18px; color: #65676b; cursor: pointer; padding: 8px; border-radius: 50%; }
.sf-post-menu { background: none; border: none; font-size: 18px; color: #65676b; cursor: pointer; padding: 8px; border-radius: 50%; }
.sf-post-menu:hover { background: #f0f2f5; }
.sf-post-menu:hover { background: #f0f2f5; }
.sf-post-content { padding: 0 16px 16px; font-size: 15px; line-height: 1.5; color: #050505; white-space: pre-wrap; }
.sf-post-content { padding: 0 16px 16px; font-size: 15px; line-height: 1.5; white-space: pre-wrap; }
.sf-post-image { width: 100%; max-height: 500px; object-fit: cover; }
.sf-post-image { width: 100%; max-height: 500px; object-fit: cover; }
.sf-post-stats { display: flex; justify-content: space-between; padding: 12px 16px; font-size: 14px; color: #65676b; border-bottom: 1px solid #e4e6eb; }
.sf-post-stats { display: flex; justify-content: space-between; padding: 12px 16px; font-size: 14px; color: #65676b; border-bottom: 1px solid #e4e6eb; }
.sf-post-stats-left { display: flex; align-items: center; gap: 6px; }
.sf-post-stats-left { display: flex; align-items: center; gap: 6px; }
.sf-reaction-icons { display: flex; }
.sf-reaction-icon { width: 20px; height: 20px; border-radius: 50%; background: #1877f2; color: white; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; }
.sf-reaction-icon { width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; margin-left: -4px; }
.sf-reaction-icon:first-child { margin-left: 0; }
.sf-reaction-icon.like { background: #1877f2; color: white; }
.sf-reaction-icon.love { background: #e91e63; color: white; }
.sf-post-actions { display: flex; padding: 4px 16px; }
.sf-post-actions { display: flex; padding: 4px 16px; }
.sf-post-action { flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 12px; background: none; border: none; font-size: 15px; font-weight: 600; color: #65676b; cursor: pointer; border-radius: 8px; }
.sf-post-action { flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 12px; background: none; border: none; font-size: 15px; font-weight: 600; color: #65676b; cursor: pointer; border-radius: 8px; }
Line 146: Line 45:
.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; overflow-x: auto; }
.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-story { display: flex; flex-direction: column; align-items: center; gap: 8px; cursor: pointer; }
.sf-story-ring { width: 68px; height: 68px; border-radius: 50%; padding: 3px; background: linear-gradient(45deg, #f09433, #e6683c, #dc2743, #cc2366, #bc1888); }
.sf-story-avatar { width: 100%; height: 100%; border-radius: 50%; border: 3px solid white; object-fit: cover; }
.sf-story-name { font-size: 12px; color: #050505; }
.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-create-story:hover { background: #d8dadf; }
.sf-modal { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6); 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(0,0,0,0.6); z-index: 1000; 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: 400px; width: 90%; }
.sf-modal-content { background: white; border-radius: 12px; padding: 24px; max-width: 400px; width: 90%; }
Line 160: Line 54:
.sf-modal-buttons { display: flex; gap: 12px; justify-content: flex-end; }
.sf-modal-buttons { display: flex; gap: 12px; justify-content: flex-end; }
.sf-modal-btn { padding: 10px 20px; border-radius: 8px; border: none; font-weight: 600; cursor: pointer; }
.sf-modal-btn { padding: 10px 20px; border-radius: 8px; border: none; font-weight: 600; cursor: pointer; }
.sf-modal-btn-cancel { background: #e4e6eb; color: #050505; }
.sf-modal-btn-cancel { background: #e4e6eb; }
.sf-modal-btn-save { background: #1877f2; color: white; }
.sf-modal-btn-save { background: #1877f2; color: white; }
#image-preview { display: none; padding: 12px 20px; background: white; margin-bottom: 20px; border-radius: 12px; }
#image-preview img { max-width: 100%; max-height: 200px; border-radius: 8px; }
</style>
</style>


<div class="sf-stories" id="stories-container">
<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-story">
        <button class="sf-create-story">+</button>
        <span class="sf-story-name">Add Story</span>
    </div>
</div>


<div class="sf-composer">
<div class="sf-composer">
    <div class="sf-composer-main">
<div class="sf-composer-main">
        <div class="sf-avatar" id="composer-avatar" onclick="openProfileModal()">
<div class="sf-avatar" id="composer-avatar"><span id="avatar-text">?</span><div class="sf-avatar-edit">Edit</div></div>
            <span id="avatar-initials"></span>
<textarea class="sf-composer-input" id="post-content" placeholder="What is on your mind?"></textarea>
            <div class="sf-avatar-edit">Edit</div>
</div>
        </div>
<div class="sf-composer-actions">
        <textarea class="sf-composer-input" id="post-content" placeholder="What is on your mind?"></textarea>
<div class="sf-action-buttons">
    </div>
<button class="sf-action-btn" id="add-image-btn">🖼️</button>
    <div class="sf-composer-actions">
<button class="sf-action-btn">😊</button>
        <div class="sf-action-buttons">
<button class="sf-action-btn">🎬</button>
            <button class="sf-action-btn" title="Add Image" onclick="promptImage()">🖼️</button>
<button class="sf-action-btn">📍</button>
            <button class="sf-action-btn" title="Emoji">😊</button>
</div>
            <button class="sf-action-btn" title="GIF">🎬</button>
<button class="sf-post-btn" id="post-btn">Post</button>
            <button class="sf-action-btn" title="Location">📍</button>
</div>
        </div>
        <button class="sf-post-btn" id="post-btn">Post</button>
    </div>
</div>
</div>


<div id="image-preview" style="display:none; padding: 0 20px 16px; background: white; margin-top: -20px; border-radius: 0 0 12px 12px;">
<div id="image-preview"><img id="preview-img"><button id="remove-image-btn" style="margin-left:10px;padding:5px 10px;">Remove</button></div>
    <div style="position: relative; display: inline-block;">
        <img id="preview-img" style="max-width: 100%; max-height: 300px; border-radius: 8px;">
        <button onclick="removeImage()" style="position: absolute; top: 8px; right: 8px; background: rgba(0,0,0,0.6); color: white; border: none; border-radius: 50%; width: 28px; height: 28px; cursor: pointer;">×</button>
    </div>
</div>


<div id="timeline-container">
<div id="timeline-container"><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></div>
    <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>
</div>


<div class="sf-modal" id="profile-modal">
<div class="sf-modal" id="profile-modal">
    <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...">
<input type="text" class="sf-modal-input" id="profile-url-input" placeholder="Enter image URL...">
        <p style="font-size: 12px; color: #65676b; margin: 0 0 12px;">Tip: Upload an image to your wiki, then paste the URL here</p>
<p style="font-size:12px;color:#65676b;margin-bottom:12px;">Upload to wiki first, then paste URL</p>
        <div class="sf-modal-buttons">
<div class="sf-modal-buttons">
            <button class="sf-modal-btn sf-modal-btn-cancel" onclick="closeProfileModal()">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" onclick="saveProfilePhoto()">Save</button>
<button class="sf-modal-btn sf-modal-btn-save" id="profile-save-btn">Save</button>
        </div>
</div>
    </div>
</div>
</div>
</div>


<script>
<script>
(function() {
mw.loader.using(['mediawiki.api']).then(function(){
    var currentUser = mw.config.get("wgUserName") || "Guest";
var user=mw.config.get('wgUserName')||'Guest';
    var profilePhoto = localStorage.getItem("sf_profile_photo_" + currentUser) || "";
var photo=localStorage.getItem('sf_photo_'+user)||'';
    var pendingImageUrl = "";
var pendingImg='';
   
var api=new mw.Api();
    function getInitials(name) {
 
        return name.split(/[\s_]+/).map(function(w) { return w[0]; }).join("").substring(0,2).toUpperCase();
function init(n){return n.split(/[\s_]+/).map(function(w){return w[0]||'';}).join('').substring(0,2).toUpperCase()||'?';}
    }
function esc(t){var d=document.createElement('div');d.textContent=t;return d.innerHTML;}
   
function ago(d){var s=Math.floor((Date.now()-d)/1000);if(s<60)return'Just now';var m=Math.floor(s/60);if(m<60)return m+'m';var h=Math.floor(m/60);if(h<24)return h+'h';return Math.floor(h/24)+'d';}
    function setAvatar(container, photo, name) {
 
        if (photo) {
function setAv(){
            container.innerHTML = "<img src=\"" + photo + "\" onerror=\"this.parentNode.innerHTML= + getInitials(name) + \"><div class=\"sf-avatar-edit\">Edit</div>";
var el=document.getElementById('composer-avatar');
        } else {
el.innerHTML=photo?'<img src="'+photo+'">':init(user);
            container.innerHTML = getInitials(name) + "<div class=\"sf-avatar-edit\">Edit</div>";
el.innerHTML+='<div class="sf-avatar-edit">Edit</div>';
        }
}
    }
setAv();
   
document.getElementById('post-content').placeholder='What is on your mind, '+user+'?';
    // Initialize
 
    var composerAvatar = document.getElementById("composer-avatar");
document.getElementById('composer-avatar').onclick=function(){
    setAvatar(composerAvatar, profilePhoto, currentUser);
document.getElementById('profile-url-input').value=photo;
    document.getElementById("post-content").placeholder = "What is on your mind, " + currentUser + "?";
document.getElementById('profile-modal').classList.add('active');
   
};
    document.getElementById("post-btn").addEventListener("click", createPost);
document.getElementById('profile-cancel-btn').onclick=function(){document.getElementById('profile-modal').classList.remove('active');};
   
document.getElementById('profile-save-btn').onclick=function(){
    loadPosts();
photo=document.getElementById('profile-url-input').value.trim();
   
localStorage.setItem('sf_photo_'+user,photo);
    window.openProfileModal = function() {
setAv();
        document.getElementById("profile-modal").classList.add("active");
document.getElementById('profile-modal').classList.remove('active');
        document.getElementById("profile-url-input").value = profilePhoto;
};
    };
 
   
document.getElementById('add-image-btn').onclick=function(){
    window.closeProfileModal = function() {
var u=prompt('Enter image URL:');
        document.getElementById("profile-modal").classList.remove("active");
if(u){pendingImg=u;document.getElementById('preview-img').src=u;document.getElementById('image-preview').style.display='block';}
    };
};
   
document.getElementById('remove-image-btn').onclick=function(){pendingImg='';document.getElementById('image-preview').style.display='none';};
    window.saveProfilePhoto = function() {
 
        var url = document.getElementById("profile-url-input").value.trim();
document.getElementById('post-btn').onclick=function(){
        profilePhoto = url;
var c=document.getElementById('post-content').value.trim();
        localStorage.setItem("sf_profile_photo_" + currentUser, url);
if(!c&&!pendingImg){alert('Write something or add image');return;}
        setAvatar(composerAvatar, profilePhoto, currentUser);
var btn=this;btn.disabled=true;btn.textContent='Posting...';
        closeProfileModal();
var p={action:'socialfeed',sfaction:'createpost',content:c||'(photo)'};
    };
if(pendingImg)p.image_url=pendingImg;
   
api.postWithToken('csrf',p).done(function(){
    window.promptImage = function() {
document.getElementById('post-content').value='';
        var url = prompt("Enter image URL:");
pendingImg='';document.getElementById('image-preview').style.display='none';
        if (url) {
btn.disabled=false;btn.textContent='Post';
            pendingImageUrl = url;
load();
            document.getElementById("preview-img").src = url;
}).fail(function(code,data){alert('Error: '+(data&&data.error?data.error.info:code));btn.disabled=false;btn.textContent='Post';});
            document.getElementById("image-preview").style.display = "block";
};
        }
 
    };
function load(){
   
api.get({action:'socialfeed',sfaction:'getposts',limit:20}).done(function(d){render(d.socialfeed.posts||[]);}).fail(function(){
    window.removeImage = function() {
document.getElementById('timeline-container').innerHTML='<div class="sf-empty"><div class="sf-empty-icon">😕</div><div class="sf-empty-text">Error loading</div></div>';
        pendingImageUrl = "";
});
        document.getElementById("image-preview").style.display = "none";
}
    };
 
   
function render(posts){
    function loadPosts() {
var c=document.getElementById('timeline-container');
        new mw.Api().get({
if(!posts.length){c.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!</div></div>';return;}
            action: "socialfeed",
var h='';
            sfaction: "getposts",
posts.forEach(function(p){
            limit: 20
var t=ago(new Date(p.created));
        }).done(function(data) {
var total=0;for(var k in p.reaction_counts)total+=p.reaction_counts[k];
            renderPosts(data.socialfeed.posts || []);
var pic=localStorage.getItem('sf_photo_'+p.username)||'';
        }).fail(function(code, data) {
var av=pic?'<img src="'+pic+'">':init(p.username);
            console.error("API Error:", code, data);
h+='<div class="sf-post"><div class="sf-post-header"><div class="sf-avatar sf-avatar-small">'+av+'</div><div class="sf-post-user-info"><div class="sf-post-username">'+esc(p.username)+'</div><div class="sf-post-meta">'+t+' · 🌐</div></div>';
            document.getElementById("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>";
if(p.username===user)h+='<button class="sf-post-menu" data-del="'+p.id+'">🗑️</button>';
        });
h+='</div><div class="sf-post-content">'+esc(p.content)+'</div>';
    }
if(p.image_url)h+='<img class="sf-post-image" src="'+p.image_url+'">';
   
h+='<div class="sf-post-stats"><div class="sf-post-stats-left">';
    function renderPosts(posts) {
if(total>0)h+='<span class="sf-reaction-icon">👍</span><span>'+total+'</span>';
        var container = document.getElementById("timeline-container");
h+='</div><span>'+p.comments+' comments</span></div>';
        if (posts.length === 0) {
h+='<div class="sf-post-actions"><button class="sf-post-action'+(p.user_reaction==='like'?' liked':'')+'" data-like="'+p.id+'">👍 Like</button><button class="sf-post-action" data-cmt="'+p.id+'">💬 Comment</button><button class="sf-post-action">↗️ Share</button></div>';
            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>";
h+='<div class="sf-comments" id="cmt-'+p.id+'" style="display:none"></div></div>';
            return;
});
        }
c.innerHTML=h;
        var html = "";
c.querySelectorAll('[data-del]').forEach(function(b){b.onclick=function(){if(confirm('Delete?'))api.postWithToken('csrf',{action:'socialfeed',sfaction:'deletepost',post_id:b.dataset.del}).done(load);};});
        posts.forEach(function(post) {
c.querySelectorAll('[data-like]').forEach(function(b){b.onclick=function(){api.postWithToken('csrf',{action:'socialfeed',sfaction:'react',post_id:b.dataset.like,reaction_type:'like'}).done(load);};});
            var timeAgo = getTimeAgo(new Date(post.created));
c.querySelectorAll('[data-cmt]').forEach(function(b){b.onclick=function(){var box=document.getElementById('cmt-'+b.dataset.cmt);if(box.style.display==='none'){box.style.display='block';loadCmt(b.dataset.cmt);}else{box.style.display='none';}};});
            var totalReactions = 0;
}
            for (var k in post.reaction_counts) totalReactions += post.reaction_counts[k];
 
            var userPhoto = localStorage.getItem("sf_profile_photo_" + post.username) || "";
function loadCmt(id){
            var avatarContent = userPhoto ? "<img src=\"" + userPhoto + "\">" : getInitials(post.username);
var box=document.getElementById('cmt-'+id);
           
api.get({action:'socialfeed',sfaction:'getcomments',post_id:id}).done(function(d){
            html += "<div class=\"sf-post\" data-id=\"" + post.id + "\">";
var cmts=d.socialfeed.comments||[];
            html += "<div class=\"sf-post-header\"><div class=\"sf-avatar sf-avatar-small\">" + avatarContent + "</div><div class=\"sf-post-user-info\"><div class=\"sf-post-username\">" + escapeHtml(post.username) + "</div><div class=\"sf-post-meta\">" + timeAgo + " · 🌐</div></div>";
var h='';
            if (post.username === currentUser) html += "<button class=\"sf-post-menu\" onclick=\"deletePost(" + post.id + ")\">🗑️</button>";
cmts.forEach(function(cm){var pic=localStorage.getItem('sf_photo_'+cm.username)||'';var av=pic?'<img src="'+pic+'">':init(cm.username);h+='<div class="sf-comment"><div class="sf-avatar sf-avatar-small">'+av+'</div><div class="sf-comment-bubble"><div class="sf-comment-author">'+esc(cm.username)+'</div><div class="sf-comment-text">'+esc(cm.content)+'</div></div></div>';});
            html += "</div>";
var myPic=photo?'<img src="'+photo+'">':init(user);
            html += "<div class=\"sf-post-content\">" + escapeHtml(post.content) + "</div>";
h+='<div class="sf-add-comment"><div class="sf-avatar sf-avatar-small">'+myPic+'</div><input class="sf-comment-input" id="cinput-'+id+'" placeholder="Write a comment..."></div>';
            if (post.image_url) html += "<img class=\"sf-post-image\" src=\"" + post.image_url + "\">";
box.innerHTML=h;
            html += "<div class=\"sf-post-stats\"><div class=\"sf-post-stats-left\">";
document.getElementById('cinput-'+id).onkeypress=function(e){if(e.key==='Enter'&&this.value.trim()){var v=this.value.trim();this.value='';api.postWithToken('csrf',{action:'socialfeed',sfaction:'comment',post_id:id,content:v}).done(function(){loadCmt(id);load();});}};
            if (totalReactions > 0) {
});
                html += "<div class=\"sf-reaction-icons\">";
}
                if (post.reaction_counts && post.reaction_counts.like) html += "<span class=\"sf-reaction-icon like\">👍</span>";
 
                if (post.reaction_counts && post.reaction_counts.love) html += "<span class=\"sf-reaction-icon love\">❤️</span>";
load();
                html += "</div><span>" + totalReactions + "</span>";
});
            }
            html += "</div><span>" + post.comments + " comments</span></div>";
            html += "<div class=\"sf-post-actions\">";
            html += "<button class=\"sf-post-action " + (post.user_reaction === "like" ? "liked" : "") + "\" onclick=\"toggleReaction(" + post.id + ")\">👍 Like</button>";
            html += "<button class=\"sf-post-action\" onclick=\"toggleComments(" + post.id + ")\">💬 Comment</button>";
            html += "<button class=\"sf-post-action\">↗️ Share</button></div>";
            html += "<div class=\"sf-comments\" id=\"comments-" + post.id + "\" style=\"display:none\"></div></div>";
        });
        container.innerHTML = html;
    }
   
    window.createPost = function() {
        var content = document.getElementById("post-content").value.trim();
        if (!content && !pendingImageUrl) return;
        document.getElementById("post-btn").disabled = true;
       
        var params = {
            action: "socialfeed",
            sfaction: "createpost",
            content: content || "(photo)"
        };
        if (pendingImageUrl) params.image_url = pendingImageUrl;
       
        new mw.Api().postWithToken("csrf", params).done(function() {
            document.getElementById("post-content").value = "";
            pendingImageUrl = "";
            document.getElementById("image-preview").style.display = "none";
            document.getElementById("post-btn").disabled = false;
            loadPosts();
        }).fail(function(c, d) {
            alert("Error: " + (d && d.error ? d.error.info : c));
            document.getElementById("post-btn").disabled = false;
        });
    };
   
    window.deletePost = function(id) {
        if (!confirm("Delete this post?")) return;
        new mw.Api().postWithToken("csrf", { action: "socialfeed", sfaction: "deletepost", post_id: id }).done(loadPosts);
    };
   
    window.toggleReaction = function(id) {
        new mw.Api().postWithToken("csrf", { action: "socialfeed", sfaction: "react", post_id: id, reaction_type: "like" }).done(loadPosts);
    };
   
    window.toggleComments = function(id) {
        var c = document.getElementById("comments-" + id);
        if (c.style.display === "none") { c.style.display = "block"; loadComments(id); }
        else { c.style.display = "none"; }
    };
   
    function loadComments(id) {
        var c = document.getElementById("comments-" + id);
        new mw.Api().get({ action: "socialfeed", sfaction: "getcomments", post_id: id }).done(function(data) {
            var comments = data.socialfeed.comments || [];
            var html = "";
            comments.forEach(function(cm) {
                var cPhoto = localStorage.getItem("sf_profile_photo_" + cm.username) || "";
                var cAvatar = cPhoto ? "<img src=\"" + cPhoto + "\">" : getInitials(cm.username);
                html += "<div class=\"sf-comment\"><div class=\"sf-avatar sf-avatar-small\">" + cAvatar + "</div><div class=\"sf-comment-bubble\"><div class=\"sf-comment-author\">" + escapeHtml(cm.username) + "</div><div class=\"sf-comment-text\">" + escapeHtml(cm.content) + "</div></div></div>";
            });
            var myPhoto = profilePhoto ? "<img src=\"" + profilePhoto + "\">" : getInitials(currentUser);
            html += "<div class=\"sf-add-comment\"><div class=\"sf-avatar sf-avatar-small\">" + myPhoto + "</div><input class=\"sf-comment-input\" placeholder=\"Write a comment...\" onkeypress=\"if(event.key===String.fromCharCode(13))addComment(" + id + ",this)\"></div>";
            c.innerHTML = html;
        });
    }
   
    window.addComment = function(id, input) {
        var content = input.value.trim();
        if (!content) return;
        new mw.Api().postWithToken("csrf", { action: "socialfeed", sfaction: "comment", post_id: id, content: content }).done(function() { loadComments(id); loadPosts(); });
    };
   
    function getTimeAgo(date) {
        var s = Math.floor((new Date() - date) / 1000);
        if (s < 60) return "Just now";
        var m = Math.floor(s / 60); if (m < 60) return m + "m";
        var h = Math.floor(m / 60); if (h < 24) return h + "h";
        var d = Math.floor(h / 24); if (d < 7) return d + "d";
        return date.toLocaleDateString();
    }
   
    function escapeHtml(t) { var d = document.createElement("div"); d.textContent = t; return d.innerHTML; }
})();
</script>
</script>
</div>
</div>
</html>
</html>

Revision as of 21:42, 2 February 2026

Add Story
?
Edit
📝
No posts yet
Be the first to share something!
Set Profile Photo

Upload to wiki first, then paste URL