User:Moonythedwarf/handyman-usernames.js

Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
let uns = {};

uns.UsernameReviewModel = function HmnUnsUsernameReviewModel(config) {
	config = config || {}; // V8 hates me for this
	OO.EventEmitter.call(this);
	OO.EmitterList.call(this);
	
	this.connect(this, {
		// N/A
	});
	
	this.aggregate({
		reportUsername: "report_username",
		watchUserContributions: "watch_user_contribs",
		unwatchUserContributions: "unwatch_user_contribs",
		
	});
	
	this.timer = setInterval(() => {this.emit("update");}, config.interval || 1000);
};

OO.initClass(uns.UsernameReviewModel);
OO.mixinClass(uns.UsernameReviewModel, OO.EventEmitter);
OO.mixinClass(uns.UsernameReviewModel, OO.EmitterList);

uns.UsernameReviewUILayout = function HmnUnsUsernameReviewUI(config, model) {
	config = config || {};

	uns.UsernameReviewUILayout.parent.call(this, {
		expanded: false
	});
	
	this.upperSect = $("<div>");
	this.lowerSect = $("<div>");
	
	this.$element.append(this.upperSect, this.lowerSect);
};

OO.inheritClass(uns.UsernameReviewUILayout, OO.ui.PanelLayout);

uns.UsernameReviewUIControls = function HmnUnsUsernameReviewUIControls(config, model) {
	config = config || {};
	
	uns.UsernameReviewUIControls.parent.call(this, config);
	OO.EventEmitter.call(this);
	
	this.base = new OO.ui.PanelLayout({
		expanded: false,
		padded: true,
		framed: true
	});
	
	this.$element.append(this.base.$element);
};

OO.inheritClass(uns.UsernameReviewUIControls, OO.ui.Widget);
OO.mixinClass(uns.UsernameReviewUIControls, OO.EventEmitter);

uns.UsernameReviewUINameFeed = function HmnUnsUsernameReviewUINameFeed(config, model) {
	config = config || {};
	
	this.slots = [];
	this.max_listing = config.max_names || 100;
	
	uns.UsernameReviewUINameFeed.parent.call(this, config);
	OO.EventEmitter.call(this);
	OO.ui.mixin.GroupElement.call(this);
	
	
	model.connect(this, {
		update: "update"
	});
	
	this.connect(this, {
		change: "list_change"
	});
	
	this.config = config;
	this.model = model;
};

OO.inheritClass(uns.UsernameReviewUINameFeed, OO.ui.Layout);
OO.mixinClass(uns.UsernameReviewUINameFeed, OO.EventEmitter);
OO.mixinClass(uns.UsernameReviewUINameFeed, OO.ui.mixin.GroupElement);

uns.UsernameReviewUINameFeed.prototype.update = function() {
	if (document.hasFocus()) {
		uns.query_user_list(this.max_listing, (events) => {
			let items = [];

			for (let i of events) {
				items.push(new uns.UsernameFeedItem({
					username: i.user,
					time: new Date(i.timestamp)
				}));
			}
			
			this.addItems(items);
		}, (err) => {
			mw.notify("retrying in a few seconds");
		});
	}
};

uns.UsernameReviewUINameFeed.prototype.list_change = function(list) {
	// short circuit out. This seems to be the only sane way to do this that isn't prodding OOUI internals for some reason.
	if (list.length > this.max_listing) {
		this.removeItems(list.slice(this.max_listing));
		return;
	}
	
	//TODO: efficiency
	this.$element.empty();
	
	for (let i of list) {
		this.$element.append(i.$element);
	}
};

uns.UsernameFeedItem = function HmnUnsUsernameFeedItem(config, model) {
	config = config || {};
	
	uns.UsernameFeedItem.parent.call(this);
	
	this.report_button = new OO.ui.ButtonWidget({
		label: "Report to UAA",
		framed: false,
		title: "Report to UAA",
		flags: "destructive"
	})
	
	this.layout = new OO.ui.HorizontalLayout({
		items: [
			new OO.ui.LabelWidget({label: `(${config.time.getUTCHours()}:${config.time.getUTCMinutes().toString().padStart(2, '0')})`}),
			new OO.ui.LabelWidget({label: $("<a>", {
				text: config.username,
				href: `/wiki/User:${config.username}`
			})}),
			this.report_button,
			
		]
	});
	
	this.$element.append(this.layout.$element);
};

OO.inheritClass(uns.UsernameFeedItem, OO.ui.Widget);
OO.mixinClass(uns.UsernameReviewUINameFeed, OO.EventEmitter);

uns.api = new mw.Api();

uns.query_user_list = function(entries, donecb, failcb) {
	
	let starttime = uns.starttime;
	
	if (!starttime) {
		let d = new Date(Date.now());
		starttime = d.getUTCFullYear() +
        '-' + (d.getUTCMonth() + 1).toString().padStart(2, '0') +
        '-' +(d.getUTCDate()).toString().padStart(2, '0') +
        'T' + (d.getUTCHours()).toString().padStart(2, '0') +
        ':' + (d.getUTCMinutes()).toString().padStart(2, '0') +
        ':' + (d.getUTCSeconds()).toString().padStart(2, '0') +
        'Z';
    }
	
	mw.notify(starttime);
	
	uns.starttime = starttime;
	
	
	uns.api.abort();
	
	uns.api.get({
		action: "query",
		format: "json",
		list: "logevents",
		letype: "newusers",
		lelimit: entries.toString(),
		lestart: starttime,
		ledir: 'older',
		lecontinue: uns.cont || undefined,
	}).fail(failcb).done((r) => {
		if (r.query.logevents[0]) {
			uns.last_timestamp = r.query.logevents[0].timestamp;
		}
		uns.cont = r.continue.lecontinue;
		donecb(r.query.logevents);
	});
};

uns.build_usernamefeed_ui = function () {
	let cfg = {};
	window.handyman.ui = {};
	window.handyman.ui.models = {};
	
	window.handyman.ui.models.unrevmodel = new uns.UsernameReviewModel();
	
	window.handyman.ui.layout = new uns.UsernameReviewUILayout(cfg, window.handyman.ui.models.unrevmodel);
	window.handyman.ui.controls = new uns.UsernameReviewUIControls(cfg, window.handyman.ui.models.unrevmodel);
	window.handyman.ui.feed = new uns.UsernameReviewUINameFeed(cfg, window.handyman.ui.models.unrevmodel);
	
	window.handyman.ui.layout.upperSect.append(window.handyman.ui.controls.$element);
	window.handyman.ui.layout.lowerSect.append(window.handyman.ui.feed.$element);
	
	$("#mw-content-text").append(window.handyman.ui.layout.$element);
};

window.handyman.uns = uns;