MediaWiki:Gadget-gsnews.js: Difference between revisions
Jump to navigation
Jump to search
Created page with "//<nowiki> →global jQuery, mediaWiki, mw, gs, gswiki, moment, ga: 'use strict'; ;(function($, mw, gs){ var portletLink, $popup, $arrow, $content, $list, news_it..." |
mNo edit summary |
||
| Line 47: | Line 47: | ||
function init() { | function init() { | ||
$content = $('<div>').addClass('gsw- | $content = $('<div>').addClass('gsw-gsnews-content'); | ||
$list = $('<ul>').addClass('news-list'); | $list = $('<ul>').addClass('news-list'); | ||
| Line 55: | Line 55: | ||
'', | '', | ||
'', | '', | ||
'pt- | 'pt-gsnews', | ||
'Gemini Staion News', | 'Gemini Staion News', | ||
null, | null, | ||
| Line 71: | Line 71: | ||
// Google analytics tracker | // Google analytics tracker | ||
if (typeof ga === 'function') { | if (typeof ga === 'function') { | ||
ga('gtag_UA_126479006_1.send', 'event', 'Gadget- | ga('gtag_UA_126479006_1.send', 'event', 'Gadget-gsnews', 'Open', 'Normal'); | ||
} | } | ||
| Line 78: | Line 78: | ||
}); | }); | ||
$arrow = $('<div>').addClass('gsw- | $arrow = $('<div>').addClass('gsw-gsnews-arrow'); | ||
$popup = $('<div>').addClass('gsw- | $popup = $('<div>').addClass('gsw-gsnews').css({ | ||
'max-width': '500px' | 'max-width': '500px' | ||
}).append( | }).append( | ||
$arrow, | $arrow, | ||
$('<h2>').html('Latest Gemini Station News'), | $('<h2>').html('Latest Gemini Station News'), | ||
$('<div>').addClass('gsw- | $('<div>').addClass('gsw-gsnews-help').html('Curated by trusted community members. <a href="/w/Help:Gadget-gsnews" target="_blank">Learn more</a>. View this feed <a href="/w/GSWiki:News" target="_blank">on a page</a>.'), | ||
$content | $content | ||
); | ); | ||
| Line 96: | Line 96: | ||
// Close popup when anywhere else is clicked | // Close popup when anywhere else is clicked | ||
$(document).click(function(e) { | $(document).click(function(e) { | ||
if (isopen && !$(e.target).closest('.gsw- | if (isopen && !$(e.target).closest('.gsw-gsnews').length) { | ||
$popup.hide(); | $popup.hide(); | ||
isopen = false; | isopen = false; | ||
| Line 109: | Line 109: | ||
// If we're on the standalone page, we should show the feed there | // If we're on the standalone page, we should show the feed there | ||
if ($('.' + standaloneClass).length) { | if ($('.' + standaloneClass).length) { | ||
$('.' + standaloneClass).addClass('gsw- | $('.' + standaloneClass).addClass('gsw-gsnews').html($content); | ||
// change the click handler on the portlet link because | // change the click handler on the portlet link because | ||
| Line 116: | Line 116: | ||
$(portletLink).find('a').off('click').click(function(e) { | $(portletLink).find('a').off('click').click(function(e) { | ||
e.preventDefault(); | e.preventDefault(); | ||
mw.notify( 'You are on the standalone page for the feed already. You do not need to open this popup.', { tag: ' | mw.notify( 'You are on the standalone page for the feed already. You do not need to open this popup.', { tag: 'gsnews' } ); | ||
}) | }) | ||
} | } | ||
| Line 168: | Line 168: | ||
function setLoading () { | function setLoading () { | ||
mw.log('Setting | mw.log('Setting gsnews as loading'); | ||
$('.gsw- | $('.gsw-gsnews-content').addClass('gsw-social-loading'); | ||
} | } | ||
function setLoadingDone () { | function setLoadingDone () { | ||
mw.log('Setting | mw.log('Setting gsnews as loading done'); | ||
$('.gsw- | $('.gsw-gsnews-content').removeClass('gsw-social-loading'); | ||
} | } | ||
| Line 185: | Line 185: | ||
function trackClick( e ) { | function trackClick( e ) { | ||
if (typeof ga === 'function') { | if (typeof ga === 'function') { | ||
ga('gtag_UA_126479006_1.send', 'event', 'Gadget- | ga('gtag_UA_126479006_1.send', 'event', 'Gadget-gsnews', 'Open link', e.data.type); | ||
} | } | ||
} | } | ||
| Line 390: | Line 390: | ||
if (itemId !== parseInt(lastItem)) { | if (itemId !== parseInt(lastItem)) { | ||
$(portletLink).find('a.oo-ui-icon-feedback') | $(portletLink).find('a.oo-ui-icon-feedback') | ||
.addClass('gsw- | .addClass('gsw-gsnews-hasunread') | ||
} else { | } else { | ||
$(portletLink).find('a.oo-ui-icon-feedback') | $(portletLink).find('a.oo-ui-icon-feedback') | ||
.removeClass('gsw- | .removeClass('gsw-gsnews-hasunread') | ||
} | } | ||
} | } | ||
Revision as of 19:46, 9 August 2021
//<nowiki>
/*global jQuery, mediaWiki, mw, gs, gswiki, moment, ga */
'use strict';
;(function($, mw, gs){
var portletLink,
$popup,
$arrow,
$content,
$list,
news_items,
isopen = false,
url = '',
lastUrl = '',
page = 1,
lastKey = 'gsw-gsnews-lastcheck',
activityKey = 'gsw-gsnews-last',
standaloneClass = 'gsw-gsnews-page',
currentSkin = mw.config.get('skin');
// Site icon overrides (hosted locally)
var srcicons = {
twitter: { regex:/twitter\./i , icon:'<img src="/images/thumb/1/1c/Twitter_news_icon.svg/240px-Twitter_news_icon.svg.png?597fa" alt="Twitter logo">' },
reddit: { regex:/reddit\./i , icon:'<img src="/images/thumb/6/68/Reddit_news_icon.svg/240px-Reddit_news_icon.svg.png?597fa" alt="Reddit logo">' },
gswiki: { regex:/gem\.wiki/i , icon:'<img src="/images/2/21/gsw_news_icon.png?3591e" alt="Gemini Station wiki logo">' },
discord: { regex:/discordapp\./i , icon:'<img src="/images/thumb/b/b2/Discord_news_icon.svg/210px-Discord_news_icon.svg.png?6438d" alt="Discord logo">' },
};
// Allow images from
var hasimg = {
twitter: true,
reddit: true,
gswiki: true,
discord: false,
unknown: true
};
function hasLocalStorage () {
// because gsw-util for some reason doesn't work here
try {
localStorage.setItem('test', 'test')
localStorage.removeItem('test')
return true
} catch (e) {
return false
}
}
function init() {
$content = $('<div>').addClass('gsw-gsnews-content');
$list = $('<ul>').addClass('news-list');
if (currentSkin !== 'minerva') { // AKA we're not on mobile
portletLink = mw.util.addPortletLink(
'p-personal',
'',
'',
'pt-gsnews',
'Gemini Staion News',
null,
$('#pt-userpage, #pt-anonuserpage')
);
$(portletLink).find('a').addClass('oo-ui-icon-feedback').click(function(e) {
e.preventDefault();
mw.log('Open/Close RS news');
if (isopen) {
$popup.hide();
isopen = false;
} else {
// Google analytics tracker
if (typeof ga === 'function') {
ga('gtag_UA_126479006_1.send', 'event', 'Gadget-gsnews', 'Open', 'Normal');
}
handleInitialLoad(false);
}
});
$arrow = $('<div>').addClass('gsw-gsnews-arrow');
$popup = $('<div>').addClass('gsw-gsnews').css({
'max-width': '500px'
}).append(
$arrow,
$('<h2>').html('Latest Gemini Station News'),
$('<div>').addClass('gsw-gsnews-help').html('Curated by trusted community members. <a href="/w/Help:Gadget-gsnews" target="_blank">Learn more</a>. View this feed <a href="/w/GSWiki:News" target="_blank">on a page</a>.'),
$content
);
$('body').append($popup);
$popup.hide();
// Reposition popup on window resize
$(window).resize(resizeEvent);
// Close popup when anywhere else is clicked
$(document).click(function(e) {
if (isopen && !$(e.target).closest('.gsw-gsnews').length) {
$popup.hide();
isopen = false;
}
});
// Check for new news items periodically (updates counter)
checkNew();
// setInterval(checkNew, 300000); lets not cause 12million hits a day.
}
// If we're on the standalone page, we should show the feed there
if ($('.' + standaloneClass).length) {
$('.' + standaloneClass).addClass('gsw-gsnews').html($content);
// change the click handler on the portlet link because
// nobody needs to use this and it might cause bugs
if (portletLink !== undefined) {
$(portletLink).find('a').off('click').click(function(e) {
e.preventDefault();
mw.notify( 'You are on the standalone page for the feed already. You do not need to open this popup.', { tag: 'gsnews' } );
})
}
handleInitialLoad(true);
}
}
function handleInitialLoad (standalone) {
mw.loader.using(['moment'], function () {
$.ajax({
dataType: 'json',
url: url,
headers: { 'Cache-Control': 'max-age=0' },
error: function (jqXHR, status, error) {
openError(jqXHR, status, error, standalone);
},
success: function (newsjson) {
mw.log('Success getting news items');
mw.log(newsjson);
if ( !(newsjson.data && newsjson.data[0]) ) {
openError({}, 'Missing news items', 'returned json contained no data, or has an unrecognised structure');
return;
}
news_items = null; // items should be cleared when opening the popup
page = 1;
$content.empty();
$list.empty();
addItems(newsjson, true);
$content.append($list);
updateLastActivity(newsjson);
if (!standalone) {
openPopup();
}
}
});
});
}
/**
* Open popup, add news items
* @return {undefined}
*/
function openPopup(newsjson, status, jqXHR) {
isopen = true;
resizeEvent();
$popup.show();
}
function setLoading () {
mw.log('Setting gsnews as loading');
$('.gsw-gsnews-content').addClass('gsw-social-loading');
}
function setLoadingDone () {
mw.log('Setting gsnews as loading done');
$('.gsw-gsnews-content').removeClass('gsw-social-loading');
}
/**
* Add items to list
* @return {undefined}
*/
function addItems(newsjson, checkActivity) {
// Google analytics tracker
function trackClick( e ) {
if (typeof ga === 'function') {
ga('gtag_UA_126479006_1.send', 'event', 'Gadget-gsnews', 'Open link', e.data.type);
}
}
if (checkActivity) {
doActivityCheck(newsjson)
}
var newestdate = moment(0);
newsjson.data.forEach(function (item) {
mw.log(item);
var dateAdded = moment(item.dateAdded);
if (!news_items || dateAdded.isAfter(news_items[0].date, 'seconds') || dateAdded.isBefore(news_items[news_items.length-1].date, 'seconds') ) {
var ltype = 'unknown',
$icon,$time,$img,$item,
excerpt = item.excerpt || '';
// Check link type
for (const t in srcicons) {
if (srcicons[t].regex.test(item.url)) {
ltype = t;
$icon = $(srcicons[t].icon);
break;
}
}
mw.log(item.url);
mw.log(ltype);
// Icon image
if (!$icon && item.icon) {
$icon = $('<img>').attr({
src: item.icon,
alt: 'website icon'
});
}
// Post date/time
if (item.dateAdded) {
var pdate = moment(item.dateAdded);
$time = $('<time>').addClass('news-date').attr({
'datetime': pdate.format(),
'title': pdate.local().format('lll')
}).text( pdate.calendar(null, { sameDay: function(){return '['+this.fromNow()+']';} }) );
} else {
$time = $('<span>').addClass('news-date').attr({ title:'Unknown date-time' }).text('');
}
// Limit excerpt length, add ...
if (excerpt.length > 300) {
excerpt = excerpt.slice(0,300) + '<b> ...</b>';
}
excerpt = excerpt.replace(/(https?:\/\/(?:.+\.)?t\.co\/[a-zA-Z0-9_]+)/g, '') // remove t.co links
excerpt = excerpt.replace(/\s+/g, ' ').trim(); // remove extra whitespace and trim
// Item jquery element
$item = $('<li>').append(
$('<a>').addClass('news-item').attr({
title: item.title,
href: item.url,
target: '_blank'
}).append(
$icon.addClass('news-icon'),
$('<span>').addClass('news-title').text(item.title),
$time,
$('<br>'),
$('<span>').addClass('news-snippet').html(excerpt)
)
);
// Post image
if (hasimg[ltype] && item.image) {
$item.find('.news-snippet').prepend(
$('<img>').addClass('news-image').attr({ src: item.image, alt: 'article image' })
);
}
if ( !news_items ) {
// No news items
news_items = [ {
id: item.id,
type: ltype,
date: dateAdded,
$element: $item
} ];
} else if ( dateAdded.isAfter(news_items[0].date, 'seconds') ) {
// Newer than last post
news_items.unshift({
id: item.id,
date: dateAdded,
$element: $item
});
} else {
// Older than last post
news_items.push({
id: item.id,
date: dateAdded,
$element: $item
});
}
}
});
mw.log(news_items);
// Generate visible list
$list.empty();
news_items.forEach(function (item) {
item.$element.find('a.news-item').click({type:item.type, id:item.id}, trackClick);
$list.append( item.$element );
});
// Refresh and show more buttons
if (newsjson.pagination && newsjson.pagination.has_more) {
$list.append($('<li>').addClass('news-refresh news-more').append(
$('<button>')
.addClass('news-more-button')
.attr({ type:'button' })
.text('Show more')
.click(function () {
page ++;
$.ajax({
dataType: 'json',
url: url + '?page=' + page,
headers: { 'Cache-Control': 'max-age=0' },
error: openError,
success: showMore
});
})
));
}
setLoadingDone();
// Update latest check time
if (hasLocalStorage()) {
try {
localStorage.setItem(lastKey, moment().format());
} catch (err) {
console.warn('Error saving last check to localStorage');
}
}
}
/**
* Open popup, show error
* @return {undefined}
*/
function openError (jqXHR, status, error, standalone) {
console.warn('Error loading news:\n' + status + ': ' + error);
$content.empty();
$content.append(
$('<p>')
.addClass('news-error')
.html('Error loading news:<br>Status: ' + status + '<br>Error msg: ' + error)
);
if (!standalone) {
isopen = true;
resizeEvent();
$popup.show();
}
}
/**
* Show more news items
* @return {undefined}
*/
function showMore(newsjson, status, jqXHR) {
$content.find('li.news-refresh').remove();
setLoading();
mw.log('Success getting more news items');
mw.log(newsjson);
if ( !(newsjson.data && newsjson.data[0]) ) {
console.warn('No news items: returned json contained no data, or has an unrecognised structure');
setLoadingDone();
return;
}
addItems(newsjson, false);
}
function doActivityCheck(newsjson) {
var lastItem;
try {
lastItem = localStorage.getItem(activityKey);
} catch (err) {
console.warn('Error loading last item from localStorage');
}
var itemId = null
if (typeof newsjson === 'object') {
itemId = newsjson.id
} else {
itemId = newsjson.data[0].id
}
if (itemId !== parseInt(lastItem)) {
$(portletLink).find('a.oo-ui-icon-feedback')
.addClass('gsw-gsnews-hasunread')
} else {
$(portletLink).find('a.oo-ui-icon-feedback')
.removeClass('gsw-gsnews-hasunread')
}
}
function updateLastActivity(newsjson) {
// save new id
try {
localStorage.setItem(activityKey, newsjson.data[0].id);
} catch (err) {
console.warn('Error saving last activity to localStorage');
}
}
/**
* Checks for new items
* @return {undefined}
*/
function checkNew() {
var last = '0';
if (hasLocalStorage()) {
try {
last = localStorage.getItem(lastKey);
} catch (err) {
console.warn('Error loading last check from localStorage');
last = '0';
}
}
var checkRead = function (newsjson, status, jqXHR) {
doActivityCheck(newsjson);
};
$.ajax({
dataType: 'json',
url: lastUrl,
headers: { 'Cache-Control': 'max-age=0' },
error: console.warn,
success: checkRead
});
}
/**
* Move popup to correct position
* @return {undefined}
*/
function resizeEvent() {
if (!isopen) {
return;
}
var offset = $(portletLink).offset(),
height = $(portletLink).outerHeight(),
width = $(portletLink).outerWidth(),
pwidth = $popup.outerWidth(),
wheight = $(window).height(),
ptop = offset.top + height + 15;
$popup.css({
top: ptop + 'px',
left: (offset.left + width/2 - pwidth/2) + 'px',
'max-height': (wheight - ptop - 7) + 'px'
});
$arrow.css({
left: (pwidth/2 - 10) + 'px'
});
}
mw.loader.using(['ext.gadget.gsw-util', 'mediawiki.util'], function () {
$(init);
});
}(jQuery, mediaWiki, gswiki));
//</nowiki>