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.
mw.loader.implement( "ext.gadget.readinglist@", {
    "main": "resources/ext.gadget.readinglist/gadget.js",
    "files": {
    "resources/ext.gadget.readinglist/gadget.js": function ( require, module, exports ) {
/**
 * When re-generating this file use:
 * http://localhost:8888/w/load.php?modules=ext.gadget.readinglist&debug=true
 */
// <nowiki>
const { showOverlay, createMembersOverlay, editListOverlay } = require( './overlays.js');
const { getCollectionsWithMembership, fromBase64, saveReadingList,
    deleteCollection, getReadingListUrl,
    addToList, toBase64 } = require( './api.js' );
const READING_LIST_URL = getReadingListUrl( mw.user.getName() );

(function () {
    if ( mw.user.isAnon() ) {
        return;
    }

    const mwuibutton = ( text, className ) => {
        const editBtn = document.createElement('button');
        editBtn.classList.add( 'mw-ui-button', className );
        editBtn.textContent = text;
        return editBtn;
    };

    function addImportFromTable() {
        Array.from( document.querySelectorAll('.wikitable') )
        .filter((node) => node.querySelectorAll('a[title]').length > 4)
        .forEach((table) => {
            const titles = {
                [window.location.host]: Array.from(table.querySelectorAll('a[title]')).map((link) => link.getAttribute('title'))
            };
            const link = document.createElement('a');
            link.textContent = 'Import into list';
            const row = document.createElement('tr');
            const col = document.createElement('td');
            col.setAttribute('colspan', table.querySelectorAll('thead').length);
            table.appendChild(row);
            const base64 = toBase64(`Imported from tablez on ${mw.config.get('wgTitle')}`, '', titles);
            link.setAttribute('href', `${READING_LIST_URL}?limport=${base64}`);
            col.appendChild(link);
            table.appendChild(col);
        } );
    }

    function addToUserMenu() {
        mw.util.addPortletLink( 'p-personal', READING_LIST_URL, 'My reading lists', 'pt-readinglists', null, 'l', 'pt-watchlist' );
    }

    function addBookmarkNextToWatchAction() {
        let link = mw.util.addPortletLink('p-views', '#', 'Bookmark', 'pt-bookmark');
        if ( !link ) {
            link = mw.util.addPortletLink('page-actions', '#', 'Bookmark', 'pt-bookmark' );
        }
        if (!link ) {
            return;
        }
        // Hack: no native support for vector icons.
        setTimeout( () => {
            link.classList.remove( 'vector-tab-noicon' );
        }, 300 );
        link.querySelector( 'a' ).classList.add(
            'mw-ui-icon',
            'mw-ui-button',
            'mw-ui-quiet',
            'mw-ui-icon-element',
            'mw-ui-icon-bookmark',
            'mw-ui-icon-small'
        )
        link.addEventListener( 'click', () => {
            const title = mw.config.get( 'wgPageName' );
            showOverlay(
                getCollectionsWithMembership( mw.user.getName(), title ).then(( collections ) => {
                    return createMembersOverlay(
                        title,
                        collections
                    );
                } )
            );
        } );
    }

    const isSpecialReadingList = mw.config.get( 'wgTitle').indexOf('ReadingListz/') > -1 ||
        (mw.config.get( 'wgTitle').indexOf('ReadingList/') > -1 && !location.host.match(/(mediawiki.org|meta.wikimedia.org)/) );

    function editList() {
        const pathSplit = window.location.pathname.split('/');
        const id = parseInt(pathSplit[4],10);
        const h1 = document.querySelector('.readinglist-collection-summary h1');
        const desc = document.querySelector('.readinglist-collection-description');
        const title = h1 ? h1.textContent : '';
        const description = desc ? desc.textContent : '';
        showOverlay(
            Promise.resolve(
                editListOverlay( id, title, description, null, () => {
                    window.location.pathname = `${READING_LIST_URL}/${id}?updated=${new Date()}`;
                } )
            )
        );
    }

    function createList() {
		showOverlay(
            Promise.resolve(
                editListOverlay( null, '', '', null, () => {
                    window.location.pathname = `${READING_LIST_URL}/?updated=${new Date()}`;
                } )
            )
        );
    }

    function deleteList() {
        const pathSplit = window.location.pathname.split('/');
        const id = parseInt(pathSplit[4],10);
        const ok = confirm('Are you sure you want to delete this list?');
        if ( ok ) {
            deleteCollection(id).then(() => {
                mw.notify('List has been deleted.');
                window.location.pathname = READING_LIST_URL;
            })
        }
    }

    // Makes Special:ReadingListz loook like Special:ReadingList
    function registerTemporaryReadingListPage() {
        if ( isSpecialReadingList ) {
            const action = mwuibutton( '' );
            const container = document.createElement('div')
            container.setAttribute('id','reading-list-container')
            $('#mw-content-text').html('').append(container)
            $('#firstHeading').text('Reading lists');
            if ( document.querySelectorAll( '.mw-portlet-associated-pages a' ).length === 0 ) {
                const link = mw.util.addPortletLink('p-associated-pages', READING_LIST_URL, 'Your lists');
                if ( link ) {
                    link.classList.add( 'vector-tab-noicon' );
                }
            }

            mw.loader.using( 'special.readinglist.scripts' );
            const callback = (mutationList, observer) => {
                for (const mutation of mutationList) {
                  if (mutation.type === 'childList') {
                    action.removeEventListener('click', createList );
                    const pathSplit = window.location.pathname.split('/');
                    // create at username
                    if ( pathSplit.length === 4 ) {
                        action.removeEventListener( 'click', deleteList );
                        action.textContent = 'Create list';
                        action.addEventListener( 'click', createList );
                        const editBtn = document.querySelector( '.readinglist-collection-summary .rl-edit-btn' );
                        if ( editBtn ) {
                            editBtn.parentNode.removeChild(editBtn);
                        }
                    } else {
                        action.textContent = 'Delete list';
                        action.removeEventListener( 'click', createList );
                        action.addEventListener( 'click', deleteList );

                        const summaryArea = document.querySelector( '.readinglist-collection-summary' );
                        const existingEdit = summaryArea.querySelector('.rl-edit-btn');
                        if ( summaryArea && !existingEdit ) {
                            const editBtn = mwuibutton( 'Edit list', 'rl-edit-btn' );
                            editBtn.addEventListener( 'click', editList );
                            summaryArea.appendChild(editBtn)
                        }
                    }

                  }
                }
            };
              
             // Create an observer instance linked to the callback function
            const observer = new MutationObserver(callback);
            const config = { attributes: true, childList: true, subtree: true };
            observer.observe(document.querySelector('#reading-list-container'), config);
            mw.util.$content[0].appendChild( action );
        }
    }

    function importFunctionality() {
        const importValue = mw.util.getParamValue('limport') || mw.util.getParamValue('lexport');
        if ( importValue ) {
            const btn = mwuibutton( 'Import this list!' );
            mw.util.$content[0].appendChild( btn );
            btn.addEventListener( 'click', () => {
                const list = fromBase64( importValue );
                saveReadingList( null, list.name, list.description ).then(( id ) => {
                    Promise.all(
                        Object.keys(list.list).map((project) =>
                            addToList( id, list.list[project], project)
                        )
                    ).then(() => {
                        mw.notify('List successfully imported!');
                        window.location.pathname = READING_LIST_URL;
                    });
                });
            } );
        }
    }

    // Can be removed when these are added to menus
    addToUserMenu();
    addBookmarkNextToWatchAction();
    // Experimental feature for testing import feature: remove whenever necessary.
    addImportFromTable();
    // @todo: Can removed when $wgReadingListsWebAuthenticatedPreviews is true everywhere.
    registerTemporaryReadingListPage();
    importFunctionality();
}());
},
    "resources/ext.gadget.readinglist/icons.json": {
    "cdxIconBookmark": "\u003Cpath d=\"M5 1a2 2 0 00-2 2v16l7-5 7 5V3a2 2 0 00-2-2z\"/\u003E",
    "cdxIconBookmarkOutline": "\u003Cpath d=\"M5 1a2 2 0 00-2 2v16l7-5 7 5V3a2 2 0 00-2-2zm10 14.25-5-3.5-5 3.5V3h10z\"/\u003E"
},
    "resources/ext.gadget.readinglist/api.js": function ( require, module, exports ) {
const api = new mw.Api();

const DEFAULT_READING_LIST_NAME = 'Saved';
const DEFAULT_READING_LIST_DESCRIPTION = 'Default list for your saved articles.';

//
// Existing API functions
//
/**
 *
 * @param {number} id of list
 * @return {JQuery.Promise<any>}
 */
 function deleteCollection( id ) {
	return api.postWithToken( 'csrf', {
			action: 'readinglists',
			list: id,
			command: 'delete'
	} );
}

/**
 * @param {string} name
 * @param {string} description
 * @param {Object} list
 * @return {string}
 */
function toBase64( name, description, list ) {
	const str = JSON.stringify( { name, description, list } );
	try {
		return window.btoa( dataStr );
	} catch ( e ) {
		return window.btoa(
			encodeURIComponent( str ).replace(
				/%([0-9A-F]{2})/g,
				function toSolidBytes( match, p1 ) {
					return String.fromCharCode( '0x' + p1 );
				}
			)
		);
	}
}

/**
 * Adapted from https://stackoverflow.com/questions/30106476/using-javascripts-atob-to-decode-base64-doesnt-properly-decode-utf-8-strings
 *
 * @param {string} data
 * @return {Object}
 */
 function fromBase64( data ) {
	let plainData;
	try {
		plainData = window.atob( data );
	} catch ( e ) {
		plainData = decodeURIComponent( window.atob( str ).split( '' ).map( ( c ) => {
			return '%' + ( '00' + c.charCodeAt( 0 ).toString( 16 ) ).slice( -2 );
		} ).join( '' ) );
	}

	return JSON.parse( plainData );
}

/**
 * Sets up the reading list feature for new users who have never used it before.
 *
 * @return {jQuery.Promise<any>}
 * @param {string|null} id if an existing collection
 * @param {string} name of list
 * @param {string} description of list
 * @return {JQuery.Promise<any>}
 */
 function saveReadingList( id, name, description ) {
	if ( id ) {
		return api.postWithToken( 'csrf', {
			action: 'readinglists',
			list: id,
			name,
			description,
			command: 'update'
		} );
	} else {
		return api.postWithToken( 'csrf', {
			action: 'readinglists',
			name,
			description,
			command: 'create'
		} ).then( ( result ) => result && result.create && result.create.id );
	}
}

/**
 * @param {string} ownerName person who owns the list
 * @param {number} [id] of the list
 * @param {string} [title] of the list
 * @return {string}
 */
 const getReadingListUrl = ( ownerName, id, title ) => {
	const READING_LIST_HOST = location.host.indexOf( 'localhost' ) > -1 ?
		'' : 'https://meta.wikimedia.org';
	let titlePath = 'ReadingLists';
	if ( ownerName ) {
		titlePath += `/${ownerName}`;
	}
	if ( id ) {
		titlePath += `/${id}`;
	}
	const titleWithName = title ? `${titlePath}/${encodeURIComponent( title )}` : titlePath;
	try {
		return READING_LIST_HOST + (
			new mw.Title( titleWithName, -1 )
		).getUrl();
	} catch ( e ) {
		// Uncaught Error: Unable to parse title
		// e.g. Special:ReadingLists/1/<script>
		return READING_LIST_HOST + (
			new mw.Title( titlePath, -1 )
		).getUrl();
	}
};

/**
 * Converts API response to WVUI compatible response.
 *
 * @param {ApiQueryResponseReadingListItem} collection from API response
 * @param {string} ownerName of collection
 * @return {Card} modified collection
 */
 const readingListToCard = ( collection, ownerName ) => {
	const description = collection.default ?
		DEFAULT_READING_LIST_DESCRIPTION : collection.description;
	const name = collection.default ? DEFAULT_READING_LIST_NAME : collection.name;
	const url = getReadingListUrl( ownerName, collection.id, name );
	return Object.assign( {}, collection, { ownerName, name, description, url } );
};

/**
 *
 * @param {string} ownerName (username)
 * @param {number[]} marked a list of collection IDs which have a certain title
 * @return {Promise<Card[]>}
 */
 function getCollections( ownerName, marked ) {
	return new Promise( ( resolve, reject ) => {
		api.get( {
			action: 'query',
			format: 'json',
			rldir: 'descending',
			rlsort: 'updated',
			meta: 'readinglists',
			formatversion: 2
		} ).then( function ( /** @type {ApiQueryResponseReadingLists} */ data ) {
			resolve(
				( data.query.readinglists || [] ).map( ( collection ) =>
					readingListToCard( collection, ownerName, marked ) )
			);
		}, function ( /** @type {string} */ err ) {
			// setup a reading list and try again.
			if ( err === 'readinglists-db-error-not-set-up' ) {
				setupCollections().then( () => getCollections( ownerName, marked ) )
					.then( ( /** @type {Card[]} */ collections ) => resolve( collections ) );
			} else {
				reject( err );
			}
		} );
	} );
}


/**
 * Sets up the reading list feature for new users who have never used it before.
 *
 * @return {jQuery.Promise<any>}
 */
 function setupCollections() {
	return api.postWithToken( 'csrf', {
		action: 'readinglists',
		command: 'setup'
	} );
}

//
// New API functions
//

/**
 *
 * @return {string}
 */
 function getCurrentProjectName() {
	// Use wgServer to avoid issues with ".m." domain
	const server = mw.config.get( 'wgServer' );
	if ( server.indexOf( 'wikipedia.beta.wmflabs' ) > -1 ) {
		return server.replace( 'wikipedia.beta.wmflabs', 'wikipedia' ).replace( 'https://', '' );
	}
	return server.indexOf( '//' ) === 0 ?
		window.location.protocol + server : server;
}

/**
 * Return the collections belonging to ownerName collections but with isMember key.
 *
 * @param {string} ownerName
 * @param {string} title to check for existence in those collections
 * @return {Function}
 */
function getCollectionsWithMembership( ownerName, title ) {
	// make sure it's an array
	return getCollections( ownerName ).then((cards) => {
		return api.get( {
			action: 'query',
			format: 'json',
			meta: 'readinglists',
			rldir: 'descending',
			rlsort: 'updated',
			rlproject: getCurrentProjectName(),
			rltitle: title,
			formatversion: 2
		} ).then( function ( /** @type {ApiQueryResponseReadingLists} */data ) {
			const marked = data.query.readinglists.map( ( collection ) => collection.id );
			return cards.map( ( card ) => {
				return Object.assign( card, {
					marked: marked.indexOf( card.id ) > -1
				} );
			} );
		} );
	});
}


/**
 * @param {number} id
 * @param {string|array} titleOrTitles
 * @param {string} [projectName]
 * @return {JQuery.Promise<any>}
 */
 function addToList( id, titleOrTitles, projectName ) {
	let project = projectName || getCurrentProjectName();
	const title = typeof titleOrTitles === 'string' ? titleOrTitles : undefined;
	const batch = typeof titleOrTitles !== 'string' ? JSON.stringify(
		titleOrTitles.map(
			( title ) => ( {
				title,
				project
			} )
		)
	) : undefined;
	project = batch ? undefined : project;

	return api.postWithToken( 'csrf', {
		action: 'readinglists',
		list: id,
		project,
		title,
		batch,
		command: 'createentry'
	} ).then( ( result ) => ( { id } ) );
}

/**
 * @param {number} id of list
 * @param {string} title of page
 * @return {JQuery.Promise<ApiQueryResponseReadingListEntryItem>}
 */
 function findItemInList( id, title ) {
	return api.get( { action: 'query', format: 'json',
		list: 'readinglistentries',
		rlelists: id
	} ).then( function ( data ) {
		const items = data.query.readinglistentries.filter(
			( /** @type {ApiQueryResponseReadingListEntryItem} */ item ) => item.title === title
		);
		if ( items.length === 0 ) {
			throw new Error( 'findItemInList doesn\'t know how to deal with pagination yet.' );
		} else {
			return items[ 0 ];
		}
	} );
}

// Note the remove from list function currently doesn't work.
// See https://phabricator.wikimedia.org/T198990
/**
 * @param {number} id
 * @param {string} title
 * @return {JQuery.Promise<any>}
 */
 function removeFromList( id, title ) {
	return findItemInList( id, title ).then( function ( entry ) {
		return api.postWithToken( 'csrf', {
			action: 'readinglists',
			entry: entry.id,
			command: 'deleteentry'
		} );
	} );
}

module.exports = {
	getReadingListUrl,
	fromBase64,
	toBase64,
	saveReadingList,

	// New:
	deleteCollection,
	removeFromList,
	addToList,
	getCollectionsWithMembership
};
},
    "resources/ext.gadget.readinglist/CollectionDialog.vue": function ( require, module, exports ) {
const { CdxButton, CdxCard, CdxIcon } = require( '@wikimedia/codex' );
const { getReadingListUrl } = require( './api.js' );
const { cdxIconBookmark, cdxIconBookmarkOutline } = require( './icons.json' );
const CdxDialog = require( './Dialog.vue' );

// @vue/component
module.exports = {
	name: 'CollectionDialog',
	components: {
		CdxDialog,
		CdxButton,
		CdxIcon,
		CdxCard
	},
	
	props: {
		collections: {
			type: Array
		}
	},
	computed: {
		collectionsUrl: () => getReadingListUrl( mw.user.getName() ),
		collectionsWithThumb() {
			return this.collections;
		},
		markedIcon: () => cdxIconBookmark,
		unmarkedIcon: () => cdxIconBookmarkOutline
	},
	data: function () {
		const selected = {};
		this.collections.forEach(( collection ) => {
			selected[collection.id] = collection.marked;
		});
		return {
			selected
		};
	},
	methods: {
		createList: function () {
			this.$emit( 'create' );
		},
		hide: function () {
			this.$emit( 'hide' );
		},
		getName: function ( id ) {
			const collections = this.collections.filter( ( c ) => c.id === id );
			if ( !collections.length ) {
				throw new Error( 'Unable to locate collection with id ' + id );
			}
			return collections[ 0 ].name;
		},
		select: function ( id ) {
			this.$emit(
				'select',
				id,
				this.selected[ id ],
				this.getName( id ),
				() => {
					this.selected[ id ] = !this.selected[ id ];
				}
			);
		}
	},
	props: {
		collections: []
	}
};;
module.exports.template = "<cdx-dialog class=\"dialog-collection\" @cancel=\"hide\" :simple=\"false\" cancel-msg=\"Cancel\" title=\"Add to existing list\"> \
		<ul> \
			<li v-for=\"(collection, i) in collectionsWithThumb\" :key=\"i\" @click=\"select(collection.id)\"> \
				<cdx-card :key=\"collection.id\" :data-selected=\"selected[collection.id]\"> \
					<template #title=\"\"> \
						{{ collection.name }} \
					<\/template> \
					<template #description=\"\"> \
						{{ collection.description }} \
					<\/template> \
					<template #supporting-text=\"\"> \
						<cdx-icon v-if=\"selected[collection.id]\" :icon=\"markedIcon\"><\/cdx-icon> \
						<cdx-icon v-else=\"\" :icon=\"unmarkedIcon\"><\/cdx-icon> \
					<\/template> \
				<\/cdx-card> \
			<\/li> \
		<\/ul> \
		<footer> \
			<cdx-button @click=\"createList\">Add to new list<\/cdx-button> \
			<a :href=\"collectionsUrl\">Manage lists<\/a> \
		<\/footer> \
	<\/cdx-dialog>";
},
    "resources/ext.gadget.readinglist/CollectionEditorDialog.vue": function ( require, module, exports ) {
const { CdxTextInput, CdxCard, CdxButton } = require( '@wikimedia/codex' );
const CdxDialog = require( './Dialog.vue' );

// @vue/component
module.exports = {
	name: 'CollectionDialog',
	components: {
		CdxDialog,
		CdxTextInput,
		CdxButton,
		CdxCard
	},
	data() {
		return {
			exists: !!this.initialTitle,
			title: this.initialTitle,
			description: this.initialDescription
		};
	},
	computed: {
		label() {
			return this.exists ? 'Edit list' : 'Create list';
		},
		getDialogTitle() {
			return !this.initialDescription ? 'Create reading list' : undefined;
		},
		isSaveDisabled() {
			return !this.title;
		},
		suggestion() {
			return {
				title: this.title,
				description: this.description
			};
		}
	},
	props: {
		initialTitle: {
			type: String,
			default: ''
		},
		initialDescription: {
			type: String,
			default: ''
		}
	},
	methods: {
		cancel() {
			this.$emit( 'hide' );
		},
		save() {
			this.$emit( 'save', this.title, this.description );
		}
	}
};;
module.exports.template = "<cdx-dialog @cancel=\"cancel\" :simple=\"true\" :title=\"getDialogTitle\"> \
		<div class=\"dialog-collection-editor-panel\"> \
			<cdx-card class=\"dialog-collection-editor-panel-preview\"> \
				<template #title=\"\"> \
					{{ title }} \
				<\/template> \
				<template #description=\"\"> \
					{{ description }} \
				<\/template> \
			<\/cdx-card> \
			<label>Name<\/label> \
			<cdx-text-input v-model=\"title\" placeholder=\"Name this list\" class=\"dialog-collection-editor-panel-input\"><\/cdx-text-input> \
			<label>Description<\/label> \
			<cdx-text-input v-model=\"description\" placeholder=\"Describe this list\" class=\"dialog-collection-input dialog-collection-editor-panel-input-description\"><\/cdx-text-input> \
		<\/div> \
		<template #footer=\"\"> \
			<cdx-button :disabled=\"isSaveDisabled\" @click=\"save\">{{ label }}<\/cdx-button> \
		<\/template> \
	<\/cdx-dialog>";
},
    "resources/ext.gadget.readinglist/Dialog.vue": function ( require, module, exports ) {
const wvuiIconClose = 'M4.34 2.93l12.73 12.73-1.41 1.41L2.93 4.35z M17.07 4.34L4.34 17.07l-1.41-1.41L15.66 2.93z';
const { CdxButton, CdxIcon } = require( '@wikimedia/codex' );

module.exports = {  
	name: 'CdxDialog',
	components: {
		CdxButton,
		CdxIcon
	},
	computed: {
		rootClass() {
			return {
				'wvui-dialog': true,
				'wvui-dialog-simple': this.simple,
				'wvui-dialog-complex': !this.simple
			};
		}
	},
	methods: {
		onContinue() {
			this.$emit( 'continue' )
		},
		onCancel() {
			this.$emit( 'cancel' );
		}
	},
	props: {
		continueDisabled: {
			type: Boolean,
			default: false
		},
		closeIcon: {
			type: String,
			default: wvuiIconClose
		},
		continueMsg: {
			type: String,
			default: ''
		},
		cancelMsg: {
			type: String,
			default: ''
		},
		title: {
			type: String,
			default: 'Title of dialog'
		},
		simple: {
			type: Boolean,
			default: true
		}
	}
};;
module.exports.template = "<div :class=\"rootClass\"> \
		<div class=\"wvui-dialog-shield\" @click=\"onCancel\"><\/div> \
		<div class=\"wvui-dialog-container\" @click.stop=\"\"> \
			<header class=\"wvui-dialog-container-heading\"> \
				<h2>{{ title }}<\/h2> \
				<cdx-icon v-if=\"cancelMsg &amp;&amp; !simple\" class=\"wvui-dialog-container-heading-cancel\" :icon=\"closeIcon\" @click=\"onCancel\">{{ cancelMsg }}<\/cdx-icon> \
			<\/header> \
			<div class=\"wvui-dialog-container-content\"> \
				<slot><\/slot> \
			<\/div> \
			<nav class=\"wvui-dialog-container-footer\"> \
				<slot name=\"footer\"><\/slot> \
			<\/nav> \
		<\/div> \
	<\/div>";
},
    "resources/ext.gadget.readinglist/overlays.js": function ( require, module, exports ) {
const CollectionDialog = require( './CollectionDialog.vue' );
const CollectionEditorDialog = require( './CollectionEditorDialog.vue' );
const Vue = require( 'vue' ).default || require( 'vue' );
const { removeFromList, addToList, saveReadingList } = require( './api.js' );

function registerOverlayArea() {
	if ( document.querySelectorAll('.readinglist-overlay-area').length ) {
		return;
	}
	const node = document.createElement('div');
	node.classList.add('readinglist-overlay-area');
	document.body.appendChild(node);
}

function hideOverlay( promise ) {
	registerOverlayArea();
	const container = document.querySelector( '.readinglist-overlay-area' );
	container.innerHTML = '';
}

function showOverlay( promise ) {
	registerOverlayArea();

	return promise.then((app) => {
		app.mount( '.readinglist-overlay-area' );
	});
}

function editListOverlay( existingID, name, description, title, onSaveFn ) {
	const onSave = onSaveFn || ( () => {} );
	return Vue.createMwApp( CollectionEditorDialog, {
		initialTitle: name,
		initialDescription: description,
		onSave: ( name, description ) => {
			hideOverlay();
			saveReadingList( existingID, name, description ).then((id) => {
				mw.notify( existingID ? 'List edited!' : 'List created!');
				if ( title ) {
					addToList( id, title ).then(() => {
						mw.notify('Added title to list!');
						onSave();
					});
				} else {
					onSave();
				}
				
			}, () => {
				mw.notify('Error creating list');
			})
			
		},
		onHide: () => {
			hideOverlay();
		}
	} );
}

/**
 *
 * @return {Object}
 */
function createMembersOverlay( title, collections ) {
	return Vue.createMwApp( CollectionDialog, {
		collections,
		onSelect: ( id, isSelected, name, callback ) => {
			if ( isSelected ) {
				removeFromList( id, title ).then( () => {
					mw.notify( isSelected ? `Removed page from ${name}` : `Added page to ${name}.` );
					callback();
				} );
			} else {
				addToList( id, title ).then( () => {
					mw.notify( isSelected ? `Removed page from ${name}` : `Added page to ${name}.` );
					callback();
				} );
			}
		},
		onCreate: () => {
			showOverlay( Promise.resolve( editListOverlay( null, '', '', title ) ) );
		},
		onHide: () => {
			hideOverlay();
		}
	} );
}

module.exports = {
	showOverlay,
	hideOverlay,
	editListOverlay,
	createMembersOverlay
};
// </nowiki>
}
}
}, {
    "css": [
        ".mw-ui-icon-vector-gadget-pt-readinglists:before {\n  background-image: linear-gradient(transparent, transparent), url(\"data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2220%22 height=%2220%22 viewBox=%220 0 20 20%22%3E%3Ctitle%3E bullet list %3C/title%3E%3Cg fill=%22%23000%22%3E%3Cpath d=%22M7 15h12v2H7zm0-6h12v2H7zm0-6h12v2H7z%22/%3E%3Ccircle cx=%223%22 cy=%224%22 r=%222%22/%3E%3Ccircle cx=%223%22 cy=%2210%22 r=%222%22/%3E%3Ccircle cx=%223%22 cy=%2216%22 r=%222%22/%3E%3C/g%3E%3C/svg%3E\");\n}\n.mw-ui-icon-bookmark:before {\n  background-image: linear-gradient(transparent, transparent), url(\"data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2220%22 height=%2220%22 viewBox=%220 0 20 20%22%3E%3Ctitle%3E bookmark outlined %3C/title%3E%3Cg fill=%22%23000%22%3E%3Cpath d=%22M5 1a2 2 0 0 0-2 2v16l7-5 7 5V3a2 2 0 0 0-2-2zm10 14.25-5-3.5-5 3.5V3h10z%22/%3E%3C/g%3E%3C/svg%3E\");\n}\n.readinglist-overlay-area {\n  z-index: 9999;\n}\n\n.dialog-collection h2 {\n  font-size: 1.2em;\n  border: 0;\n  font-weight: bold;\n  padding: 0;\n  margin: 0.5em 0 0;\n}\n.dialog-collection footer {\n  text-align: center;\n  position: absolute;\n  bottom: 10px;\n  left: 0;\n  right: 0;\n}\n.dialog-collection footer a {\n  color: #333;\n}\n.dialog-collection ul {\n  height: calc(100% - 100px);\n  overflow: scroll;\n}\n.dialog-collection li {\n  display: flex;\n  align-items: center;\n}\n.dialog-collection li .cdx-card__text,\n.dialog-collection li .cdx-card {\n  flex-grow: 1;\n}\n.dialog-collection li .cdx-card__text__supporting-text {\n  justify-content: end;\n  display: flex;\n}\n\n.dialog-collection-editor-panel {\n  min-width: 300px;\n}\n.dialog-collection-editor-panel-preview {\n  border-top: 1px solid rgba(0, 0, 0, 0.2);\n  border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n}\n.dialog-collection-editor-panel label {\n  margin-top: 2em;\n  font-weight: bold;\n  margin-bottom: 0.5em;\n  display: block;\n}\n.dialog-collection-editor-panel-input {\n  margin-bottom: 20px;\n  display: block;\n}\n.dialog-collection-editor-panel-input-description {\n  margin-bottom: 20px;\n}\n\n.wvui-dialog {\n  z-index: 1;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  box-sizing: border-box;\n}\n.wvui-dialog-shield,\n.wvui-dialog {\n  position: fixed;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n}\n.wvui-dialog-shield {\n  opacity: 0.5;\n  background: #ccc;\n}\n.wvui-dialog-container \u003E * {\n  margin: 0;\n}\n.wvui-dialog-container-button + .wvui-dialog-container-button {\n  margin-top: 0.5em;\n}\n.wvui-dialog-container-heading {\n  display: flex;\n}\n.wvui-dialog-container-heading h2 {\n  flex-grow: 1;\n  margin: 0;\n}\n.wvui-dialog-container {\n  position: absolute;\n  background: white;\n  margin: auto;\n}\n.wvui-dialog-container-heading-continue {\n  display: none;\n}\n.wvui-dialog-simple {\n  align-items: center;\n}\n.wvui-dialog-simple .wvui-dialog-container-heading {\n  margin: 0 0 1.25em;\n}\n.wvui-dialog-simple .wvui-dialog-container {\n  padding: 1.5em;\n  position: absolute;\n  background: white;\n  margin: auto;\n  max-width: 400px;\n}\n.wvui-dialog-complex .wvui-dialog-container {\n  height: 100%;\n  max-height: 500px;\n}\n.wvui-dialog-complex .wvui-dialog-container-content {\n  overflow: scroll;\n  height: 100%;\n}\n@media all and (max-width: 400px) {\n  .wvui-dialog-complex {\n    align-items: flex-start;\n  }\n  .wvui-dialog-complex .wvui-dialog-container {\n    width: 100%;\n    padding-bottom: 40px;\n    box-sizing: border-box;\n  }\n  .wvui-dialog-complex .wvui-dialog-container-heading-cancel {\n    order: 1;\n    padding: 16px;\n  }\n  .wvui-dialog-complex .wvui-dialog-container-heading h2 {\n    order: 2;\n    margin-left: 16px;\n    padding: 16px 0;\n  }\n  .wvui-dialog-complex .wvui-dialog-container-heading-continue {\n    display: block;\n    order: 3;\n  }\n  .wvui-dialog-complex .wvui-dialog-container-content {\n    padding: 16px;\n    box-sizing: border-box;\n  }\n  .wvui-dialog-complex .wvui-dialog-container-footer {\n    display: none;\n  }\n}\n@media all and (min-width: 400px) {\n  .wvui-dialog-complex .wvui-dialog-container {\n    width: 500px;\n    max-width: 500px;\n  }\n  .wvui-dialog-complex .wvui-dialog-container-heading {\n    margin: 1.25em 1.25em 1em;\n  }\n  .wvui-dialog-complex .wvui-dialog-container-content {\n    margin: 0 1.25em;\n  }\n  .wvui-dialog-complex .wvui-dialog-container-footer {\n    border-top: 1px solid gray;\n    padding: 1.25em;\n    text-align: right;\n  }\n}\n.wvui-dialog-container-footer {\n  margin-top: 1em;\n}"
    ]
} );