User:Docmoates/Social: Difference between revisions

From XMethod Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 49: Line 49:
.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: 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: 400px; width: 90%; }
.sf-modal-content { background: white; border-radius: 12px; padding: 24px; max-width: 450px; width: 90%; }
.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 58: Line 58:
#image-preview { display: none; padding: 12px 20px; background: white; margin-bottom: 20px; border-radius: 12px; }
#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; }
#image-preview img { max-width: 100%; max-height: 200px; border-radius: 8px; }
.sf-tabs { display: flex; border-bottom: 2px solid #e4e6eb; margin-bottom: 16px; }
.sf-tab { flex: 1; padding: 12px; text-align: center; cursor: pointer; font-weight: 600; color: #65676b; border-bottom: 2px solid transparent; margin-bottom: -2px; }
.sf-tab.active { color: #1877f2; border-bottom-color: #1877f2; }
.sf-tab-content { display: none; }
.sf-tab-content.active { display: block; }
.sf-upload-zone { border: 2px dashed #ccc; border-radius: 12px; padding: 40px 20px; text-align: center; cursor: pointer; transition: 0.2s; margin-bottom: 12px; }
.sf-upload-zone:hover { border-color: #1877f2; background: #f0f7ff; }
.sf-upload-zone.dragover { border-color: #1877f2; background: #e3f2fd; }
.sf-upload-icon { font-size: 48px; margin-bottom: 12px; }
.sf-upload-text { color: #65676b; font-size: 14px; }
.sf-upload-progress { display: none; margin-top: 12px; }
.sf-progress-bar { height: 8px; background: #e4e6eb; border-radius: 4px; overflow: hidden; }
.sf-progress-fill { height: 100%; background: #1877f2; width: 0%; transition: width 0.3s; }
.sf-preview-thumb { max-width: 100%; max-height: 150px; border-radius: 8px; margin-top: 12px; }
</style>
</style>


Line 90: Line 104:
<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="image-modal">
<div class="sf-modal-content">
<div class="sf-modal-title">Add Photo</div>
<div class="sf-tabs">
<div class="sf-tab active" data-tab="upload">Upload</div>
<div class="sf-tab" data-tab="url">From URL</div>
</div>
<div class="sf-tab-content active" id="tab-upload">
<div class="sf-upload-zone" id="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="file-input" accept="image/*" style="display:none">
</div>
<div class="sf-upload-progress" id="upload-progress">
<div class="sf-progress-bar"><div class="sf-progress-fill" id="progress-fill"></div></div>
<p style="font-size:12px;color:#65676b;margin-top:8px;" id="upload-status">Uploading...</p>
</div>
<img class="sf-preview-thumb" id="upload-preview" style="display:none">
</div>
<div class="sf-tab-content" id="tab-url">
<input type="text" class="sf-modal-input" id="image-url-input" placeholder="Paste image URL...">
<img class="sf-preview-thumb" id="url-preview" style="display:none">
</div>
<div class="sf-modal-buttons">
<button class="sf-modal-btn sf-modal-btn-cancel" id="image-cancel-btn">Cancel</button>
<button class="sf-modal-btn sf-modal-btn-save" id="image-add-btn">Add Image</button>
</div>
</div>
</div>
</div>
Line 100: Line 144:
var pendingImg='';
var pendingImg='';
var api=new mw.Api();
var api=new mw.Api();
var uploadedFile=null;


function init(n){return n.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()||'?';}
Line 128: Line 173:
});
});


// Image modal tabs
document.querySelectorAll('.sf-tab').forEach(function(tab){
tab.addEventListener('click',function(){
document.querySelectorAll('.sf-tab').forEach(function(t){t.classList.remove('active');});
document.querySelectorAll('.sf-tab-content').forEach(function(c){c.classList.remove('active');});
tab.classList.add('active');
gel('tab-'+tab.dataset.tab).classList.add('active');
});
});
// Image modal
gel('add-image-btn').addEventListener('click',function(){
gel('add-image-btn').addEventListener('click',function(){
var u=prompt('Enter image URL:');
gel('image-modal').classList.add('active');
if(u){pendingImg=u;gel('preview-img').src=u;gel('image-preview').style.display='block';}
gel('image-url-input').value='';
gel('url-preview').style.display='none';
gel('upload-preview').style.display='none';
gel('upload-progress').style.display='none';
uploadedFile=null;
});
gel('image-cancel-btn').addEventListener('click',function(){
gel('image-modal').classList.remove('active');
});
});
// File upload zone
var uploadZone=gel('upload-zone');
var fileInput=gel('file-input');
uploadZone.addEventListener('click',function(){fileInput.click();});
uploadZone.addEventListener('dragover',function(e){e.preventDefault();uploadZone.classList.add('dragover');});
uploadZone.addEventListener('dragleave',function(){uploadZone.classList.remove('dragover');});
uploadZone.addEventListener('drop',function(e){
e.preventDefault();
uploadZone.classList.remove('dragover');
if(e.dataTransfer.files.length>0)handleFile(e.dataTransfer.files[0]);
});
fileInput.addEventListener('change',function(){
if(fileInput.files.length>0)handleFile(fileInput.files[0]);
});
function handleFile(file){
if(!file.type.startsWith('image/')){alert('Please select an image file');return;}
uploadedFile=file;
var reader=new FileReader();
reader.onload=function(e){
gel('upload-preview').src=e.target.result;
gel('upload-preview').style.display='block';
};
reader.readAsDataURL(file);
}
// URL preview
gel('image-url-input').addEventListener('input',function(){
var url=this.value.trim();
if(url){
gel('url-preview').src=url;
gel('url-preview').style.display='block';
}else{
gel('url-preview').style.display='none';
}
});
// Add image button
gel('image-add-btn').addEventListener('click',function(){
var activeTab=document.querySelector('.sf-tab.active').dataset.tab;
if(activeTab==='url'){
var url=gel('image-url-input').value.trim();
if(url){
pendingImg=url;
gel('preview-img').src=url;
gel('image-preview').style.display='block';
gel('image-modal').classList.remove('active');
}else{
alert('Please enter an image URL');
}
}else{
if(uploadedFile){
uploadImage(uploadedFile);
}else{
alert('Please select an image to upload');
}
}
});
function uploadImage(file){
gel('upload-progress').style.display='block';
gel('progress-fill').style.width='10%';
gel('upload-status').textContent='Preparing upload...';
var filename='SocialFeed_'+user+'_'+Date.now()+'.'+file.name.split('.').pop();
api.get({action:'query',meta:'tokens',type:'csrf'}).then(function(data){
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',data.query.tokens.csrftoken);
formData.append('format','json');
formData.append('ignorewarnings','1');
var xhr=new XMLHttpRequest();
xhr.open('POST',mw.util.wikiScript('api'),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+'%';
}
};
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('upload-status').textContent='Upload complete!';
pendingImg=resp.upload.imageinfo.url;
gel('preview-img').src=pendingImg;
gel('image-preview').style.display='block';
setTimeout(function(){gel('image-modal').classList.remove('active');},500);
}else if(resp.upload.warnings){
gel('upload-status').textContent='Warning: '+JSON.stringify(resp.upload.warnings);
}
}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(){pendingImg='';gel('image-preview').style.display='none';});
gel('remove-image-btn').addEventListener('click',function(){pendingImg='';gel('image-preview').style.display='none';});



Revision as of 02:49, 3 February 2026

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

Upload to wiki first, then paste URL

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

Uploading...