User:Docmoates/common.js

From XMethod Wiki
Revision as of 12:05, 3 February 2026 by Docmoates (talk | contribs)
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* SocialFeed - Instagram-style social page */
if (mw.config.get("wgPageName") === "User:Docmoates/Social") {
mw.loader.using(["mediawiki.api", "mediawiki.util"]).then(function() {
var $=jQuery,api=new mw.Api(),apiUrl=mw.util.wikiScript("api"),user=mw.config.get("wgUserName")||"Guest";
var ud={photo:localStorage.getItem("sf_photo_"+user)||"",cover:localStorage.getItem("sf_cover_"+user)||"",bio:localStorage.getItem("sf_bio_"+user)||"",name:localStorage.getItem("sf_name_"+user)||user};
var pp={image:"",video:"",location:""},uf={};

function gi(n){return(n||"?").split(/[\s_]+/).map(function(w){return(w[0]||"").toUpperCase();}).join("").substring(0,2)||"?";}
function esc(t){var d=document.createElement("div");d.textContent=t;return d.innerHTML;}
function ago(ds){var s=Math.floor((Date.now()-new Date(ds))/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 av(pic,name,sz){if(pic)return'<img src="'+esc(pic)+'">';var c=sz==="s"?"sa-comment-avatar-placeholder":sz==="p"?"sa-post-avatar-placeholder":sz==="c"?"sa-composer-avatar-placeholder":"sa-profile-pic-placeholder";return'<div class="'+c+'">'+gi(name)+'</div>';}
function om(id){$("#"+id).addClass("open");}
function cm(id){$("#"+id).removeClass("open");}
function upload(file,pre,prog){return api.getToken("csrf").then(function(tk){var ext=file.name.split(".").pop()||"jpg",fn=pre+"_"+user+"_"+Date.now()+"."+ext,fd=new FormData();fd.append("action","upload");fd.append("filename",fn);fd.append("file",file);fd.append("token",tk);fd.append("format","json");fd.append("ignorewarnings","1");return $.ajax({url:apiUrl,type:"POST",data:fd,processData:false,contentType:false,xhr:function(){var x=$.ajaxSettings.xhr();if(x.upload&&prog)x.upload.addEventListener("progress",function(e){if(e.lengthComputable)prog(Math.round(e.loaded/e.total*100));});return x;}});}).then(function(r){if(r.upload&&r.upload.imageinfo)return r.upload.imageinfo.url;throw new Error(r.error?r.error.info:"Upload failed");});}

// Clean CSS
var css='\
#social-app{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;background:#fafafa;min-height:100vh;padding-bottom:60px}\
#social-app *{box-sizing:border-box}\
.sa-cover{height:220px;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);position:relative;border-radius:0 0 12px 12px}\
.sa-cover img{width:100%;height:100%;object-fit:cover;border-radius:0 0 12px 12px}\
.sa-cover-edit{position:absolute;bottom:16px;right:16px;background:rgba(0,0,0,0.6);color:#fff;border:none;padding:10px 18px;border-radius:8px;cursor:pointer;font-size:14px;font-weight:500;display:flex;align-items:center;gap:6px}\
.sa-cover-edit:hover{background:rgba(0,0,0,0.8)}\
.sa-profile-section{max-width:935px;margin:0 auto;padding:0 20px}\
.sa-profile-header{display:flex;align-items:flex-start;gap:40px;margin-top:-60px;position:relative;z-index:10;padding:0 20px}\
.sa-profile-pic{width:168px;height:168px;border-radius:50%;border:6px solid #fff;background:#fff;overflow:hidden;cursor:pointer;flex-shrink:0;box-shadow:0 4px 20px rgba(0,0,0,0.15)}\
.sa-profile-pic img{width:100%;height:100%;object-fit:cover}\
.sa-profile-pic-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;color:#fff;font-size:56px;font-weight:600}\
.sa-profile-info{flex:1;padding-top:80px}\
.sa-profile-top{display:flex;align-items:center;gap:24px;margin-bottom:20px;flex-wrap:wrap}\
.sa-username{font-size:32px;font-weight:300;margin:0;color:#262626}\
.sa-edit-btn{background:#0095f6;color:#fff;border:none;padding:10px 28px;border-radius:8px;font-weight:600;cursor:pointer;font-size:14px;transition:background 0.2s}\
.sa-edit-btn:hover{background:#1877f2}\
.sa-stats{display:flex;gap:40px;margin-bottom:20px}\
.sa-stat{text-align:center}\
.sa-stat-num{font-weight:700;font-size:20px;color:#262626;display:block}\
.sa-stat-label{color:#8e8e8e;font-size:14px}\
.sa-bio{max-width:450px;line-height:1.6;color:#262626}\
.sa-bio-name{font-weight:600;margin-bottom:4px}\
.sa-main{max-width:680px;margin:40px auto 0;padding:0 20px}\
.sa-stories{display:flex;gap:20px;padding:20px 0;overflow-x:auto;margin-bottom:24px}\
.sa-story{display:flex;flex-direction:column;align-items:center;gap:8px;cursor:pointer}\
.sa-story-ring{width:80px;height:80px;border-radius:50%;padding:3px;background:linear-gradient(45deg,#f09433,#e6683c,#dc2743,#cc2366,#bc1888)}\
.sa-story-ring.add{background:linear-gradient(135deg,#e8e8e8,#d0d0d0)}\
.sa-story-inner{width:100%;height:100%;border-radius:50%;border:3px solid #fff;overflow:hidden;background:#fafafa;display:flex;align-items:center;justify-content:center;font-size:28px;color:#0095f6;font-weight:300}\
.sa-story-inner img{width:100%;height:100%;object-fit:cover}\
.sa-story-name{font-size:12px;color:#262626;max-width:80px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}\
.sa-composer{background:#fff;border:1px solid #dbdbdb;border-radius:16px;margin-bottom:24px;overflow:hidden}\
.sa-composer-top{display:flex;gap:16px;padding:20px}\
.sa-composer-avatar{width:48px;height:48px;border-radius:50%;overflow:hidden;flex-shrink:0}\
.sa-composer-avatar img{width:100%;height:100%;object-fit:cover}\
.sa-composer-avatar-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;color:#fff;font-size:18px;font-weight:600}\
.sa-composer-input{flex:1;border:none;resize:none;font-size:16px;min-height:80px;outline:none;font-family:inherit;line-height:1.5}\
.sa-composer-input::placeholder{color:#8e8e8e}\
.sa-composer-preview{padding:0 20px 20px;display:none}\
.sa-composer-preview.show{display:block}\
.sa-composer-preview-inner{position:relative;display:inline-block}\
.sa-composer-preview img{max-width:100%;max-height:300px;border-radius:12px}\
.sa-composer-preview-remove{position:absolute;top:10px;right:10px;width:32px;height:32px;border-radius:50%;background:rgba(0,0,0,0.7);color:#fff;border:none;cursor:pointer;font-size:18px;display:flex;align-items:center;justify-content:center}\
.sa-composer-location{padding:0 20px 16px;font-size:14px;color:#0095f6;display:none;align-items:center;gap:8px}\
.sa-composer-location.show{display:flex}\
.sa-composer-location button{background:none;border:none;cursor:pointer;color:#8e8e8e;font-size:16px}\
.sa-composer-actions{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-top:1px solid #efefef}\
.sa-composer-buttons{display:flex;gap:8px}\
.sa-icon-btn{width:44px;height:44px;border:none;background:none;cursor:pointer;font-size:22px;border-radius:50%;transition:background 0.2s;display:flex;align-items:center;justify-content:center}\
.sa-icon-btn:hover{background:#f0f0f0}\
.sa-post-btn{background:#0095f6;color:#fff;border:none;padding:12px 32px;border-radius:8px;font-weight:600;cursor:pointer;font-size:14px;transition:all 0.2s}\
.sa-post-btn:disabled{opacity:0.3;cursor:default}\
.sa-post-btn:not(:disabled):hover{background:#1877f2}\
.sa-feed{display:flex;flex-direction:column;gap:24px}\
.sa-post{background:#fff;border:1px solid #dbdbdb;border-radius:16px;overflow:hidden}\
.sa-post-header{display:flex;align-items:center;gap:14px;padding:16px 20px}\
.sa-post-avatar{width:44px;height:44px;border-radius:50%;overflow:hidden}\
.sa-post-avatar img{width:100%;height:100%;object-fit:cover}\
.sa-post-avatar-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;color:#fff;font-size:16px;font-weight:600}\
.sa-post-user{flex:1}\
.sa-post-username{font-weight:600;font-size:15px;color:#262626}\
.sa-post-meta{font-size:12px;color:#8e8e8e;margin-top:2px}\
.sa-post-menu{background:none;border:none;cursor:pointer;font-size:20px;color:#262626;padding:8px;border-radius:50%}\
.sa-post-menu:hover{background:#f0f0f0}\
.sa-post-content{padding:0 20px 16px;font-size:15px;line-height:1.5;white-space:pre-wrap;color:#262626}\
.sa-post-location{padding:0 20px 12px;font-size:13px;color:#0095f6}\
.sa-post-media{background:#fafafa}\
.sa-post-media img{width:100%;max-height:600px;object-fit:contain}\
.sa-post-media video{width:100%;max-height:600px}\
.sa-post-media iframe{width:100%;height:400px;border:none}\
.sa-post-actions{display:flex;gap:20px;padding:16px 20px}\
.sa-post-action{background:none;border:none;cursor:pointer;font-size:26px;padding:0;transition:transform 0.15s}\
.sa-post-action:hover{transform:scale(1.15)}\
.sa-post-action.liked{color:#ed4956}\
.sa-post-likes{padding:0 20px 10px;font-weight:600;font-size:15px;color:#262626}\
.sa-post-comments-count{padding:0 20px 10px;font-size:14px;color:#8e8e8e;cursor:pointer}\
.sa-post-comments-count:hover{color:#262626}\
.sa-post-time{padding:0 20px 16px;font-size:11px;color:#8e8e8e;text-transform:uppercase;letter-spacing:0.5px}\
.sa-post-comment-form{display:flex;gap:16px;padding:16px 20px;border-top:1px solid #efefef;align-items:center}\
.sa-post-comment-input{flex:1;border:none;font-size:14px;outline:none;font-family:inherit}\
.sa-post-comment-input::placeholder{color:#8e8e8e}\
.sa-post-comment-submit{background:none;border:none;color:#0095f6;font-weight:600;cursor:pointer;font-size:14px;padding:8px 12px;border-radius:6px}\
.sa-post-comment-submit:hover{background:#f0f7ff}\
.sa-comments-section{display:none;padding:0 20px 16px;max-height:300px;overflow-y:auto}\
.sa-comments-section.show{display:block}\
.sa-comment{display:flex;gap:12px;margin-bottom:14px}\
.sa-comment-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;flex-shrink:0}\
.sa-comment-avatar img{width:100%;height:100%;object-fit:cover}\
.sa-comment-avatar-placeholder{width:100%;height:100%;background:linear-gradient(135deg,#667eea,#764ba2);display:flex;align-items:center;justify-content:center;color:#fff;font-size:12px;font-weight:600}\
.sa-comment-body{flex:1}\
.sa-comment-text{font-size:14px;line-height:1.4;color:#262626}\
.sa-comment-text strong{font-weight:600}\
.sa-comment-time{font-size:12px;color:#8e8e8e;margin-top:4px}\
.sa-empty{text-align:center;padding:80px 20px;background:#fff;border:1px solid #dbdbdb;border-radius:16px}\
.sa-empty-icon{font-size:72px;margin-bottom:20px;opacity:0.8}\
.sa-empty-title{font-size:26px;font-weight:300;margin-bottom:12px;color:#262626}\
.sa-empty-text{color:#8e8e8e;font-size:15px}\
.sa-modal{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.7);z-index:1000;align-items:center;justify-content:center;padding:20px}\
.sa-modal.open{display:flex}\
.sa-modal-content{background:#fff;border-radius:16px;width:100%;max-width:480px;max-height:90vh;overflow:auto;animation:modalSlide 0.2s ease}\
@keyframes modalSlide{from{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}\
.sa-modal-header{display:flex;align-items:center;justify-content:space-between;padding:20px;border-bottom:1px solid #dbdbdb}\
.sa-modal-title{font-weight:600;font-size:18px;color:#262626}\
.sa-modal-close{background:none;border:none;font-size:28px;cursor:pointer;color:#262626;line-height:1}\
.sa-modal-body{padding:24px}\
.sa-tabs{display:flex;border-bottom:1px solid #dbdbdb}\
.sa-tab{flex:1;padding:18px;text-align:center;cursor:pointer;font-weight:600;color:#8e8e8e;border-bottom:2px solid transparent;margin-bottom:-1px;transition:all 0.2s}\
.sa-tab:hover{color:#262626}\
.sa-tab.active{color:#262626;border-bottom-color:#262626}\
.sa-tab-panel{display:none;padding:24px}\
.sa-tab-panel.active{display:block}\
.sa-upload-zone{border:2px dashed #dbdbdb;border-radius:12px;padding:48px 24px;text-align:center;cursor:pointer;transition:all 0.2s}\
.sa-upload-zone:hover{border-color:#0095f6;background:#f8fbff}\
.sa-upload-zone.dragover{border-color:#0095f6;background:#e8f4ff}\
.sa-upload-zone input{display:none}\
.sa-upload-icon{font-size:56px;margin-bottom:16px}\
.sa-upload-text{color:#8e8e8e;font-size:15px}\
.sa-upload-text span{color:#0095f6;font-weight:600}\
.sa-input{width:100%;padding:16px;border:1px solid #dbdbdb;border-radius:10px;font-size:15px;margin-bottom:16px;outline:none;transition:border-color 0.2s;font-family:inherit}\
.sa-input:focus{border-color:#262626}\
.sa-textarea{width:100%;padding:16px;border:1px solid #dbdbdb;border-radius:10px;font-size:15px;margin-bottom:16px;outline:none;resize:vertical;min-height:100px;font-family:inherit;line-height:1.5}\
.sa-textarea:focus{border-color:#262626}\
.sa-preview-img{width:100%;max-height:200px;object-fit:contain;border-radius:10px;margin-top:16px;display:none}\
.sa-preview-img.show{display:block}\
.sa-progress{height:4px;background:#efefef;border-radius:2px;margin-top:16px;overflow:hidden;display:none}\
.sa-progress.show{display:block}\
.sa-progress-bar{height:100%;background:linear-gradient(90deg,#0095f6,#00d4ff);width:0;transition:width 0.3s}\
.sa-btn-row{display:flex;gap:12px;margin-top:24px}\
.sa-btn{flex:1;padding:16px;border:none;border-radius:10px;font-weight:600;font-size:15px;cursor:pointer;transition:all 0.2s}\
.sa-btn-primary{background:#0095f6;color:#fff}\
.sa-btn-primary:hover{background:#1877f2}\
.sa-btn-secondary{background:#efefef;color:#262626}\
.sa-btn-secondary:hover{background:#dbdbdb}\
.sa-story-viewer{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:#1a1a1a;z-index:2000;align-items:center;justify-content:center}\
.sa-story-viewer.open{display:flex}\
.sa-story-viewer-content{position:relative;max-width:420px;width:100%}\
.sa-story-viewer-progress{position:absolute;top:20px;left:20px;right:20px;height:3px;background:rgba(255,255,255,0.3);border-radius:2px}\
.sa-story-viewer-progress-bar{height:100%;background:#fff;width:0;border-radius:2px}\
.sa-story-viewer-header{position:absolute;top:32px;left:20px;right:20px;display:flex;align-items:center;gap:12px;color:#fff}\
.sa-story-viewer-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;border:2px solid #fff}\
.sa-story-viewer-avatar img{width:100%;height:100%;object-fit:cover}\
.sa-story-viewer-name{font-weight:600;font-size:15px}\
.sa-story-viewer-close{position:absolute;top:20px;right:20px;background:none;border:none;color:#fff;font-size:32px;cursor:pointer;z-index:10}\
.sa-story-viewer img{max-width:100%;max-height:85vh;border-radius:12px}\
@media(max-width:768px){\
.sa-profile-header{flex-direction:column;align-items:center;text-align:center;margin-top:-50px;gap:0}\
.sa-profile-pic{width:130px;height:130px;margin-bottom:16px}\
.sa-profile-info{padding-top:0}\
.sa-profile-top{justify-content:center}\
.sa-stats{justify-content:center;gap:32px}\
.sa-bio{margin:0 auto}\
.sa-cover{height:180px}\
}';
$("<style>").text(css).appendTo("head");

// Build HTML
var h='<div class="sa-cover" id="cover-area">'+(ud.cover?'<img src="'+esc(ud.cover)+'">':'')+'<button class="sa-cover-edit" id="edit-cover-btn">πŸ“· Edit Cover</button></div>';
h+='<div class="sa-profile-section"><div class="sa-profile-header"><div class="sa-profile-pic" id="profile-pic">'+av(ud.photo,user,"")+'</div><div class="sa-profile-info"><div class="sa-profile-top"><h1 class="sa-username" id="display-name">'+esc(ud.name)+'</h1><button class="sa-edit-btn" id="edit-profile-btn">Edit Profile</button></div><div class="sa-stats"><div class="sa-stat"><span class="sa-stat-num" id="post-count">0</span><span class="sa-stat-label">posts</span></div><div class="sa-stat"><span class="sa-stat-num">0</span><span class="sa-stat-label">followers</span></div><div class="sa-stat"><span class="sa-stat-num">0</span><span class="sa-stat-label">following</span></div></div><div class="sa-bio" id="bio-display">'+(ud.bio?'<div class="sa-bio-name">'+esc(ud.name)+'</div>'+esc(ud.bio).replace(/\n/g,"<br>"):"Click Edit Profile to add a bio")+'</div></div></div></div>';
h+='<div class="sa-main"><div class="sa-stories" id="stories-container"></div>';
h+='<div class="sa-composer"><div class="sa-composer-top"><div class="sa-composer-avatar" id="composer-avatar">'+av(ud.photo,user,"c")+'</div><textarea class="sa-composer-input" id="post-input" placeholder="What\'s on your mind, '+esc(user.split(/[\s_]/)[0])+'?"></textarea></div><div class="sa-composer-preview" id="post-preview"><div class="sa-composer-preview-inner"><button class="sa-composer-preview-remove" id="remove-media">&times;</button></div></div><div class="sa-composer-location" id="post-location">πŸ“ <span></span><button id="remove-location">&times;</button></div><div class="sa-composer-actions"><div class="sa-composer-buttons"><button class="sa-icon-btn" id="btn-add-photo" title="Add photo">πŸ–ΌοΈ</button><button class="sa-icon-btn" id="btn-add-video" title="Add video">🎬</button><button class="sa-icon-btn" id="btn-add-location" title="Add location">πŸ“</button><button class="sa-icon-btn" id="btn-add-emoji" title="Add emoji">😊</button></div><button class="sa-post-btn" id="btn-submit-post" disabled>Post</button></div></div>';
h+='<div class="sa-feed" id="feed-container"></div></div>';

// Modals
h+='<div class="sa-modal" id="modal-edit-profile"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Edit Profile</span><button class="sa-modal-close" data-close="modal-edit-profile">&times;</button></div><div class="sa-modal-body"><label style="font-weight:600;display:block;margin-bottom:10px">Display Name</label><input class="sa-input" id="input-display-name" value="'+esc(ud.name)+'"><label style="font-weight:600;display:block;margin-bottom:10px">Bio</label><textarea class="sa-textarea" id="input-bio" placeholder="Tell people about yourself...">'+esc(ud.bio)+'</textarea><div class="sa-btn-row"><button class="sa-btn sa-btn-secondary" data-close="modal-edit-profile">Cancel</button><button class="sa-btn sa-btn-primary" id="save-profile">Save</button></div></div></div></div>';
h+='<div class="sa-modal" id="modal-profile-pic"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Change Profile Photo</span><button class="sa-modal-close" data-close="modal-profile-pic">&times;</button></div><div class="sa-tabs"><div class="sa-tab active" data-panel="panel-pic-upload">Upload</div><div class="sa-tab" data-panel="panel-pic-url">URL</div></div><div class="sa-tab-panel active" id="panel-pic-upload"><div class="sa-upload-zone" id="zone-profile-pic"><input type="file" accept="image/*"><div class="sa-upload-icon">πŸ“·</div><div class="sa-upload-text">Drag photo here or <span>browse</span></div></div><div class="sa-progress" id="progress-profile-pic"><div class="sa-progress-bar"></div></div><img class="sa-preview-img" id="preview-profile-pic"></div><div class="sa-tab-panel" id="panel-pic-url"><input class="sa-input" id="input-pic-url" placeholder="Paste image URL..."><img class="sa-preview-img" id="preview-pic-url"></div><div class="sa-btn-row" style="padding:0 24px 24px"><button class="sa-btn sa-btn-secondary" data-close="modal-profile-pic">Cancel</button><button class="sa-btn sa-btn-primary" id="save-profile-pic">Save</button></div></div></div>';
h+='<div class="sa-modal" id="modal-cover"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Change Cover Photo</span><button class="sa-modal-close" data-close="modal-cover">&times;</button></div><div class="sa-tabs"><div class="sa-tab active" data-panel="panel-cover-upload">Upload</div><div class="sa-tab" data-panel="panel-cover-url">URL</div></div><div class="sa-tab-panel active" id="panel-cover-upload"><div class="sa-upload-zone" id="zone-cover"><input type="file" accept="image/*"><div class="sa-upload-icon">πŸ–ΌοΈ</div><div class="sa-upload-text">Drag photo here or <span>browse</span></div></div><div class="sa-progress" id="progress-cover"><div class="sa-progress-bar"></div></div><img class="sa-preview-img" id="preview-cover"></div><div class="sa-tab-panel" id="panel-cover-url"><input class="sa-input" id="input-cover-url" placeholder="Paste image URL..."><img class="sa-preview-img" id="preview-cover-url"></div><div class="sa-btn-row" style="padding:0 24px 24px"><button class="sa-btn sa-btn-secondary" data-close="modal-cover">Cancel</button><button class="sa-btn sa-btn-primary" id="save-cover">Save</button></div></div></div>';
h+='<div class="sa-modal" id="modal-photo"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Add Photo</span><button class="sa-modal-close" data-close="modal-photo">&times;</button></div><div class="sa-tabs"><div class="sa-tab active" data-panel="panel-photo-upload">Upload</div><div class="sa-tab" data-panel="panel-photo-url">URL</div></div><div class="sa-tab-panel active" id="panel-photo-upload"><div class="sa-upload-zone" id="zone-photo"><input type="file" accept="image/*"><div class="sa-upload-icon">πŸ“€</div><div class="sa-upload-text">Drag photo here or <span>browse</span></div></div><div class="sa-progress" id="progress-photo"><div class="sa-progress-bar"></div></div><img class="sa-preview-img" id="preview-photo"></div><div class="sa-tab-panel" id="panel-photo-url"><input class="sa-input" id="input-photo-url" placeholder="Paste image URL..."><img class="sa-preview-img" id="preview-photo-url"></div><div class="sa-btn-row" style="padding:0 24px 24px"><button class="sa-btn sa-btn-secondary" data-close="modal-photo">Cancel</button><button class="sa-btn sa-btn-primary" id="add-photo">Add Photo</button></div></div></div>';
h+='<div class="sa-modal" id="modal-story"><div class="sa-modal-content"><div class="sa-modal-header"><span class="sa-modal-title">Add to Story</span><button class="sa-modal-close" data-close="modal-story">&times;</button></div><div class="sa-tabs"><div class="sa-tab active" data-panel="panel-story-upload">Upload</div><div class="sa-tab" data-panel="panel-story-url">URL</div></div><div class="sa-tab-panel active" id="panel-story-upload"><div class="sa-upload-zone" id="zone-story"><input type="file" accept="image/*"><div class="sa-upload-icon">πŸ“·</div><div class="sa-upload-text">Drag photo here or <span>browse</span></div></div><div class="sa-progress" id="progress-story"><div class="sa-progress-bar"></div></div><img class="sa-preview-img" id="preview-story"></div><div class="sa-tab-panel" id="panel-story-url"><input class="sa-input" id="input-story-url" placeholder="Paste image URL..."><img class="sa-preview-img" id="preview-story-url"></div><div class="sa-btn-row" style="padding:0 24px 24px"><button class="sa-btn sa-btn-secondary" data-close="modal-story">Cancel</button><button class="sa-btn sa-btn-primary" id="add-story">Share to Story</button></div></div></div>';
h+='<div class="sa-story-viewer" id="story-viewer"><div class="sa-story-viewer-content"><div class="sa-story-viewer-progress"><div class="sa-story-viewer-progress-bar" id="sv-prog"></div></div><button class="sa-story-viewer-close" id="close-story-viewer">&times;</button><div class="sa-story-viewer-header"><div class="sa-story-viewer-avatar" id="story-viewer-avatar"></div><div class="sa-story-viewer-name" id="story-viewer-name"></div></div><img id="story-viewer-image" src=""></div></div>';

$("#social-app").html(h);
var $a=$("#social-app");

// Events
$a.on("click","[data-close]",function(){cm($(this).data("close"));});
$a.on("click",".sa-modal",function(e){if($(e.target).hasClass("sa-modal"))cm(this.id);});
$a.on("click",".sa-tab",function(){var $t=$(this),$p=$("#"+$t.data("panel"));$t.addClass("active").siblings().removeClass("active");$p.addClass("active").siblings(".sa-tab-panel").removeClass("active");});

function suz(zid,pid,prid,fk){var $z=$("#"+zid),$i=$z.find("input"),$pv=$("#"+pid),$pr=$("#"+prid);$z.on("click",function(){$i.click();});$z.on("dragover",function(e){e.preventDefault();$(this).addClass("dragover");});$z.on("dragleave drop",function(){$(this).removeClass("dragover");});$z.on("drop",function(e){e.preventDefault();var f=e.originalEvent.dataTransfer.files;if(f.length)hf(f[0]);});$i.on("change",function(){if(this.files.length)hf(this.files[0]);});function hf(f){uf[fk]=f;if(f.type.startsWith("image/")){var r=new FileReader();r.onload=function(e){$pv.attr("src",e.target.result).addClass("show");};r.readAsDataURL(f);}}return{reset:function(){uf[fk]=null;$pv.removeClass("show").attr("src","");$pr.removeClass("show").find(".sa-progress-bar").css("width",0);$i.val("");},setP:function(p){$pr.addClass("show").find(".sa-progress-bar").css("width",p+"%");}};}
var upPic=suz("zone-profile-pic","preview-profile-pic","progress-profile-pic","profilePic");
var upCov=suz("zone-cover","preview-cover","progress-cover","cover");
var upPho=suz("zone-photo","preview-photo","progress-photo","photo");
var upSto=suz("zone-story","preview-story","progress-story","story");

$("#input-pic-url").on("input",function(){var v=$(this).val();$("#preview-pic-url").attr("src",v).toggleClass("show",!!v);});
$("#input-cover-url").on("input",function(){var v=$(this).val();$("#preview-cover-url").attr("src",v).toggleClass("show",!!v);});
$("#input-photo-url").on("input",function(){var v=$(this).val();$("#preview-photo-url").attr("src",v).toggleClass("show",!!v);});
$("#input-story-url").on("input",function(){var v=$(this).val();$("#preview-story-url").attr("src",v).toggleClass("show",!!v);});

$("#edit-profile-btn").on("click",function(){om("modal-edit-profile");});
$("#save-profile").on("click",function(){ud.name=$("#input-display-name").val().trim()||user;ud.bio=$("#input-bio").val().trim();localStorage.setItem("sf_name_"+user,ud.name);localStorage.setItem("sf_bio_"+user,ud.bio);$("#display-name").text(ud.name);$("#bio-display").html(ud.bio?'<div class="sa-bio-name">'+esc(ud.name)+'</div>'+esc(ud.bio).replace(/\n/g,"<br>"):"Click Edit Profile to add a bio");cm("modal-edit-profile");});

$("#profile-pic").on("click",function(){upPic.reset();$("#input-pic-url").val("");$("#preview-pic-url").removeClass("show");om("modal-profile-pic");});
$("#save-profile-pic").on("click",function(){var ap=$("#modal-profile-pic .sa-tab.active").data("panel");if(ap==="panel-pic-url"){var u=$("#input-pic-url").val().trim();if(u)savePic(u);else alert("Please enter a URL");}else if(uf.profilePic){upload(uf.profilePic,"ProfilePic",upPic.setP).then(savePic).fail(function(){alert("Upload error");});}else alert("Please select an image");});
function savePic(u){ud.photo=u;localStorage.setItem("sf_photo_"+user,u);$("#profile-pic").html(av(u,user,""));$("#composer-avatar").html(av(u,user,"c"));cm("modal-profile-pic");upPic.reset();}

$a.on("click","#edit-cover-btn",function(){upCov.reset();$("#input-cover-url").val("");$("#preview-cover-url").removeClass("show");om("modal-cover");});
$("#save-cover").on("click",function(){var ap=$("#modal-cover .sa-tab.active").data("panel");if(ap==="panel-cover-url"){var u=$("#input-cover-url").val().trim();if(u)saveCov(u);else alert("Please enter a URL");}else if(uf.cover){upload(uf.cover,"Cover",upCov.setP).then(saveCov).fail(function(){alert("Upload error");});}else alert("Please select an image");});
function saveCov(u){ud.cover=u;localStorage.setItem("sf_cover_"+user,u);$("#cover-area").html('<img src="'+u+'"><button class="sa-cover-edit" id="edit-cover-btn">πŸ“· Edit Cover</button>');cm("modal-cover");upCov.reset();}

$("#btn-add-photo").on("click",function(){upPho.reset();$("#input-photo-url").val("");$("#preview-photo-url").removeClass("show");om("modal-photo");});
$("#add-photo").on("click",function(){var ap=$("#modal-photo .sa-tab.active").data("panel");if(ap==="panel-photo-url"){var u=$("#input-photo-url").val().trim();if(u){pp.image=u;$("#post-preview").addClass("show").find(".sa-composer-preview-inner").html('<button class="sa-composer-preview-remove" id="remove-media">&times;</button><img src="'+u+'">');upd();cm("modal-photo");}else alert("Please enter a URL");}else if(uf.photo){upload(uf.photo,"Post",upPho.setP).then(function(u){pp.image=u;$("#post-preview").addClass("show").find(".sa-composer-preview-inner").html('<button class="sa-composer-preview-remove" id="remove-media">&times;</button><img src="'+u+'">');upd();cm("modal-photo");upPho.reset();}).fail(function(){alert("Upload error");});}else alert("Please select an image");});

$a.on("click","#remove-media",function(){pp.image="";pp.video="";$("#post-preview").removeClass("show");upd();});

$("#btn-add-location").on("click",function(){var l=prompt("Enter location:");if(l){pp.location=l;$("#post-location").addClass("show").find("span").text(l);}});
$a.on("click","#remove-location",function(){pp.location="";$("#post-location").removeClass("show");});
$("#btn-add-emoji").on("click",function(){var e=prompt("Enter emoji:");if(e){var $i=$("#post-input")[0];var s=$i.selectionStart,v=$i.value;$i.value=v.slice(0,s)+e+v.slice($i.selectionEnd);$i.selectionStart=$i.selectionEnd=s+e.length;$i.focus();upd();}});

$("#post-input").on("input",upd);
function upd(){var h=$("#post-input").val().trim()||pp.image||pp.video;$("#btn-submit-post").prop("disabled",!h);}

$("#btn-submit-post").on("click",function(){var t=$("#post-input").val().trim();if(!t&&!pp.image&&!pp.video){alert("Please add some content");return;}var $b=$(this);$b.prop("disabled",true).text("Posting...");var p={action:"socialfeed",sfaction:"createpost",content:t||"(media)"};if(pp.image)p.image_url=pp.image;if(pp.video)p.video_url=pp.video;if(pp.location)p.location=pp.location;api.postWithToken("csrf",p).then(function(){$("#post-input").val("");pp={image:"",video:"",location:""};$("#post-preview").removeClass("show");$("#post-location").removeClass("show");$b.prop("disabled",true).text("Post");loadP();}).fail(function(c,d){alert("Error: "+(d&&d.error?d.error.info:c));$b.prop("disabled",false).text("Post");});});

$a.on("click","#add-story-btn",function(){upSto.reset();$("#input-story-url").val("");$("#preview-story-url").removeClass("show");om("modal-story");});
$("#add-story").on("click",function(){var ap=$("#modal-story .sa-tab.active").data("panel");function ps(u){api.postWithToken("csrf",{action:"socialfeed",sfaction:"createstory",image_url:u}).then(function(){cm("modal-story");upSto.reset();loadS();}).fail(function(c,d){alert("Error: "+(d&&d.error?d.error.info:c));});}if(ap==="panel-story-url"){var u=$("#input-story-url").val().trim();if(u)ps(u);else alert("Please enter a URL");}else if(uf.story){upload(uf.story,"Story",upSto.setP).then(ps).fail(function(){alert("Upload error");});}else alert("Please select an image");});

var sto;
$a.on("click",".sa-story[data-story-url]",function(){var u=$(this).data("story-url"),n=$(this).data("story-user"),p=localStorage.getItem("sf_photo_"+n)||"";$("#story-viewer-image").attr("src",u);$("#story-viewer-name").text(n);$("#story-viewer-avatar").html(av(p,n,"s"));$("#story-viewer").addClass("open");var $pb=$("#sv-prog");$pb.css("width","0");setTimeout(function(){$pb.css({width:"100%",transition:"width 5s linear"});},10);clearTimeout(sto);sto=setTimeout(function(){$("#story-viewer").removeClass("open");$pb.css({width:"0",transition:"none"});},5000);});
$("#close-story-viewer,#story-viewer").on("click",function(e){if(e.target.id==="close-story-viewer"||e.target.id==="story-viewer"){$("#story-viewer").removeClass("open");$("#sv-prog").css({width:"0",transition:"none"});clearTimeout(sto);}});

$a.on("click",".sa-post-action[data-like]",function(){var id=$(this).data("like");api.postWithToken("csrf",{action:"socialfeed",sfaction:"react",post_id:id,reaction_type:"like"}).then(loadP);});
$a.on("click",".sa-post-menu[data-delete]",function(){if(confirm("Delete this post?")){api.postWithToken("csrf",{action:"socialfeed",sfaction:"deletepost",post_id:$(this).data("delete")}).then(loadP);}});
$a.on("click",".sa-post-comments-count",function(){var id=$(this).data("post"),$s=$("#comments-"+id);if($s.hasClass("show"))$s.removeClass("show");else{$s.addClass("show");loadC(id);}});
$a.on("keypress",".sa-post-comment-input",function(e){if(e.which===13){var $i=$(this),t=$i.val().trim(),id=$i.data("post");if(t){$i.val("").prop("disabled",true);api.postWithToken("csrf",{action:"socialfeed",sfaction:"comment",post_id:id,content:t}).then(function(){$i.prop("disabled",false);loadC(id);loadP();}).fail(function(){$i.prop("disabled",false);});}}});

function loadP(){api.get({action:"socialfeed",sfaction:"getposts",limit:20}).then(function(r){var ps=(r.socialfeed&&r.socialfeed.posts)||[];$("#post-count").text(ps.length);if(!ps.length){$("#feed-container").html('<div class="sa-empty"><div class="sa-empty-icon">πŸ“·</div><div class="sa-empty-title">Share Photos</div><div class="sa-empty-text">When you share photos, they will appear here.</div></div>');return;}var h=ps.map(function(p){var up=localStorage.getItem("sf_photo_"+p.username)||"",tr=0;for(var k in p.reaction_counts)tr+=p.reaction_counts[k];var m="";if(p.image_url)m='<div class="sa-post-media"><img src="'+esc(p.image_url)+'"></div>';if(p.video_url){if(p.video_url.match(/youtube|youtu\.be/)){var vi=(p.video_url.match(/(?:v=|youtu\.be\/)([^&]+)/)||[])[1];if(vi)m='<div class="sa-post-media"><iframe src="https://www.youtube.com/embed/'+vi+'" allowfullscreen></iframe></div>';}else m='<div class="sa-post-media"><video src="'+esc(p.video_url)+'" controls></video></div>';}var lo=p.location?'<div class="sa-post-location">πŸ“ '+esc(p.location)+'</div>':"";var del=p.username===user?'<button class="sa-post-menu" data-delete="'+p.id+'">πŸ—‘οΈ</button>':"";var lc=p.user_reaction==="like"?" liked":"";return'<div class="sa-post"><div class="sa-post-header"><div class="sa-post-avatar">'+av(up,p.username,"p")+'</div><div class="sa-post-user"><div class="sa-post-username">'+esc(p.username)+'</div><div class="sa-post-meta">'+ago(p.created)+'</div></div>'+del+'</div>'+(p.content&&p.content!=="(media)"?'<div class="sa-post-content">'+esc(p.content)+'</div>':"")+lo+m+'<div class="sa-post-actions"><button class="sa-post-action'+lc+'" data-like="'+p.id+'">'+(p.user_reaction==="like"?"❀️":"🀍")+'</button><button class="sa-post-action">πŸ’¬</button><button class="sa-post-action">πŸ“€</button><button class="sa-post-action" style="margin-left:auto">πŸ”–</button></div>'+(tr?'<div class="sa-post-likes">'+tr+" like"+(tr>1?"s":"")+"</div>":"")+(p.comments?'<div class="sa-post-comments-count" data-post="'+p.id+'">View all '+p.comments+" comment"+(p.comments>1?"s":"")+"</div>":"")+'<div class="sa-comments-section" id="comments-'+p.id+'"></div><div class="sa-post-time">'+ago(p.created)+'</div><div class="sa-post-comment-form"><input class="sa-post-comment-input" data-post="'+p.id+'" placeholder="Add a comment..."><button class="sa-post-comment-submit">Post</button></div></div>';}).join("");$("#feed-container").html(h);}).fail(function(){$("#feed-container").html('<div class="sa-empty"><div class="sa-empty-icon">πŸ˜•</div><div class="sa-empty-title">Oops!</div><div class="sa-empty-text">Could not load posts. Try refreshing.</div></div>');});}
function loadC(id){api.get({action:"socialfeed",sfaction:"getcomments",post_id:id}).then(function(r){var cs=(r.socialfeed&&r.socialfeed.comments)||[];var h=cs.map(function(c){var up=localStorage.getItem("sf_photo_"+c.username)||"";return'<div class="sa-comment"><div class="sa-comment-avatar">'+av(up,c.username,"s")+'</div><div class="sa-comment-body"><div class="sa-comment-text"><strong>'+esc(c.username)+"</strong> "+esc(c.content)+'</div><div class="sa-comment-time">'+ago(c.created)+"</div></div></div>";}).join("");$("#comments-"+id).html(h||'<div style="color:#8e8e8e;padding:8px 0">No comments yet</div>');});}
function loadS(){api.get({action:"socialfeed",sfaction:"getstories"}).then(function(r){var ss=(r.socialfeed&&r.socialfeed.stories)||[];var h='<div class="sa-story"><div class="sa-story-ring add"><div class="sa-story-inner" id="add-story-btn">+</div></div><div class="sa-story-name">Your story</div></div>';h+=ss.map(function(s){var up=localStorage.getItem("sf_photo_"+s.username)||"";return'<div class="sa-story" data-story-url="'+esc(s.image_url)+'" data-story-user="'+esc(s.username)+'"><div class="sa-story-ring"><div class="sa-story-inner">'+av(up,s.username,"s")+'</div></div><div class="sa-story-name">'+esc(s.username)+"</div></div>";}).join("");$("#stories-container").html(h);}).fail(function(){});}

loadP();
loadS();
});
}