summaryrefslogtreecommitdiff
blob: 56764ff7eaecaa87d9612263c87a4dc744f87ee8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
( function () {
	// To allow users to cancel a thanks in the event of an accident, the action is delayed.
	var THANKS_DELAY = 2000,
		mobile = mw.mobileFrontend.require( 'mobile.startup' ),
		Button = mobile.Button,
		Icon = mobile.Icon,
		msgOptions = {
			// tag ensures that only one message in workflow is shown at any time
			tag: 'thanks'
		};
	/**
	 * Attempt to execute a thank operation for a given edit
	 *
	 * @param {string} name The username of the user who made the edit
	 * @param {string} revision The revision the user created
	 * @param {string} recipientGender The gender of the user who made the edit
	 * @return {jQuery.Promise} The thank operation's status.
	 */
	function thankUser( name, revision, recipientGender ) {
		return ( new mw.Api() ).postWithToken( 'csrf', {
			action: 'thank',
			rev: revision,
			source: 'mobilediff'
		} ).then( function () {
			mw.notify( mw.msg( 'thanks-button-action-completed', name, recipientGender, mw.user ),
				msgOptions );
		}, function ( errorCode ) {
			switch ( errorCode ) {
				case 'invalidrevision':
					mw.notify( mw.msg( 'thanks-error-invalidrevision' ), msgOptions );
					break;
				case 'ratelimited':
					mw.notify( mw.msg( 'thanks-error-ratelimited', recipientGender ), msgOptions );
					break;
				default:
					mw.notify( mw.msg( 'thanks-error-undefined', errorCode ), msgOptions );
			}
		} );
	}

	/**
	 * Disables the thank button marking the user as thanked
	 *
	 * @param {jQuery} $button used for thanking
	 * @param {string} gender The gender of the user who made the edit
	 * @return {jQuery} $button now disabled
	 */
	function disableThanks( $button, gender ) {
		return $button
			.addClass( 'thanked' )
			.prop( 'disabled', true )
			.text( mw.msg( 'thanks-button-thanked', mw.user, gender ) );
	}

	/**
	 * Create a thank button for a given edit
	 *
	 * @param {string} name The username of the user who made the edit
	 * @param {string} rev The revision the user created
	 * @param {string} gender The gender of the user who made the edit
	 * @return {jQuery|null} The HTML of the button.
	 */
	function createThankLink( name, rev, gender ) {
		var timeout,
			button = new Button( {
				progressive: true,
				additionalClassNames: 'mw-mf-action-button'
			} ),
			$button = button.$el;

		// append icon
		new Icon( {
			name: 'userTalk',
			glyphPrefix: 'thanks',
			hasText: true,
			label: mw.msg( 'thanks-button-thank', mw.user, gender )
		} ).$el.appendTo( $button );

		// Don't make thank button for self
		if ( name === mw.config.get( 'wgUserName' ) ) {
			return null;
		}
		// See if user has already been thanked for this edit
		if ( mw.config.get( 'wgThanksAlreadySent' ) ) {
			return disableThanks( $button, gender );
		}

		function cancelThanks( $btn ) {
			// Hide the notification
			$( '.mw-notification' ).hide();
			// Clear the queued thanks!
			clearTimeout( timeout );
			timeout = null;
			$btn.prop( 'disabled', false );
		}

		function queueThanks( $btn ) {
			var $msg = $( '<div>' ).addClass( 'mw-thanks-notification' ).text(
				mw.msg( 'thanks-button-action-queued', name, gender )
			);
			$( '<a>' ).text( mw.msg( 'thanks-button-action-cancel' ) ).appendTo( $msg );
			mw.notify( $msg, msgOptions );
			// Make it possible to cancel
			$msg.find( 'a' ).on( 'click', function () {
				cancelThanks( $btn );
			} );
			timeout = setTimeout( function () {
				timeout = null;
				thankUser( name, rev, gender ).then( function () {
					disableThanks( $btn, gender );
				} );
			}, THANKS_DELAY );
		}

		return $button.on( 'click', function () {
			var $this = $( this );
			$this.prop( 'disabled', true );
			// eslint-disable-next-line no-jquery/no-class-state
			if ( !$this.hasClass( 'thanked' ) && !timeout ) {
				queueThanks( $this );
			}
		} );
	}

	/**
	 * Initialise a thank button in the given container.
	 *
	 * @param {jQuery} $user existing element with data attributes associated describing a user.
	 * @param {jQuery} $container to render button in
	 */
	function init( $user, $container ) {
		var username = $user.data( 'user-name' ),
			rev = $user.data( 'revision-id' ),
			gender = $user.data( 'user-gender' ),
			$thankBtn;

		$thankBtn = createThankLink( username, rev, gender );
		if ( $thankBtn ) {
			$thankBtn.prependTo( $container );
		}

	}

	$( function () {
		init( $( '.mw-mf-user' ), $( '#mw-mf-userinfo' ) );
	} );

	// Expose for testing purposes
	mw.thanks = $.extend( {}, mw.thanks || {}, {
		_mobileDiffInit: init
	} );
}() );