|
|
1번째 줄: |
1번째 줄: |
| var api = new mw.Api();
| | import '/wiki/사용자:Hsl0/연구소/2.js'; |
| var gadgetsList = Object.keys(mw.loader.moduleRegistry).reduce(function(arr, key) {
| |
| if(key.startsWith('ext.gadget.')) arr.push(key.slice(11));
| |
| return arr;
| |
| }, []);
| |
| var needed = [];
| |
| var ignored = mw.user.options.get('userjs-gadgethelper-ignored');
| |
| ignored = ignored? ignored.split('|') : [];
| |
| var allowed = getAllowedGadgets();
| |
| var ignoredChanged = 0;
| |
| | |
| function getAllowedGadgets() {
| |
| var allowed = [];
| |
| var options = mw.user.options.values;
| |
| | |
| for(var key in options) {
| |
| if(key.startsWith('gadget-') && +options[key]) allowed.push(key.slice(7));
| |
| }
| |
| | |
| return allowed;
| |
| }
| |
| | |
| function getSelected(form) {
| |
| return $(form).find('input[type=checkbox]:checked').map(function() {
| |
| return this.name;
| |
| }).get().filter(function(name) {
| |
| return name;
| |
| });
| |
| }
| |
| | |
| function getUnselected(form) {
| |
| return $(form).find('input[type=checkbox]:not(:checked)').map(function() {
| |
| return this.name;
| |
| }).get().filter(function(name) {
| |
| return name;
| |
| });
| |
| }
| |
| | |
| | |
| $('.gadgethelper').each(function() {
| |
| needed = needed.concat(this.dataset.using.split(' '));
| |
| });
| |
| | |
| needed = needed.filter(function(gadget) {
| |
| return gadgetsList.includes(gadget) && !allowed.includes(gadget);
| |
| });
| |
| | |
| function SelectDialog(config) {
| |
| SelectDialog.super.call(this, config);
| |
| }
| |
| OO.inheritClass(SelectDialog, OO.ui.ProcessDialog);
| |
| | |
| SelectDialog.static.name = 'GadgetSelectDialog';
| |
| SelectDialog.static.title = '소도구 선택';
| |
| SelectDialog.static.actions = [
| |
| {
| |
| modes: 'default',
| |
| action: 'execute',
| |
| label: '실행',
| |
| flags: ['primary', 'progressive']
| |
| },
| |
| {
| |
| modes: 'ignored',
| |
| action: 'clear',
| |
| label: '해제',
| |
| flags: ['primary', 'progressive']
| |
| },
| |
| {
| |
| modes: 'default',
| |
| action: 'close',
| |
| label: '닫기',
| |
| flags: 'safe'
| |
| },
| |
| {
| |
| modes: 'ignored',
| |
| action: 'cancel',
| |
| label: '취소',
| |
| flags: 'safe'
| |
| },
| |
| {
| |
| modes: 'default',
| |
| action: 'go-ignored',
| |
| label: '무시된 소도구 보기'
| |
| },
| |
| | |
| ];
| |
| if(!mw.user.isAnon()) SelectDialog.static.actions.push({
| |
| modes: 'default',
| |
| action: 'go-allowed',
| |
| label: '항상 실행하는 소도구 관리'
| |
| });
| |
| | |
| SelectDialog.prototype.initialize = function() {
| |
| SelectDialog.super.prototype.initialize.apply(this, arguments);
| |
| | |
| this.defaultMessage = new OO.ui.PanelLayout({
| |
| expanded: false,
| |
| classes: ['gadgethelper-message'],
| |
| text: '이 문서가 정상적으로 작동하려면 다음 소도구가 필요합니다. 일시적으로 실행할 소도구를 선택해 주세요.'
| |
| });
| |
| this.defaultForm = new OO.ui.FormLayout();
| |
| this.defaultPanel = new OO.ui.PanelLayout({
| |
| padded: true,
| |
| expanded: true,
| |
| content: [this.defaultMessage, this.defaultForm]
| |
| });
| |
|
| |
| this.loading = new OO.ui.PanelLayout({
| |
| padded: true,
| |
| expanded: false,
| |
| text: '소도구 정보를 불러오고 있습니다... 잠시만 기다려 주세요.'
| |
| });
| |
| this.executing = new OO.ui.PanelLayout({
| |
| padded: true,
| |
| expanded: false,
| |
| hidden: true,
| |
| text: '소도구를 실행하는 중입니다...'
| |
| });
| |
| this.executing.toggle(false);
| |
| this.saving = new OO.ui.PanelLayout({
| |
| padded: true,
| |
| expanded: false,
| |
| hidden: true,
| |
| text: '설정을 저장하고 있습니다...'
| |
| });
| |
| this.saving.toggle(false);
| |
| | |
| this.ignoredMessage = new OO.ui.PanelLayout({
| |
| expanded: false,
| |
| classes: ['gadgethelper-message'],
| |
| text: '무시한 소도구의 목록입니다. 해제할 소도구를 선택해 주세요.'
| |
| });
| |
| this.ignoredForm = new OO.ui.FormLayout();
| |
| this.ignoredPanel = new OO.ui.PanelLayout({
| |
| padded: true,
| |
| expanded: true,
| |
| content: [this.ignoredMessage, this.ignoredForm]
| |
| });
| |
| | |
| this.stackLayout = new OO.ui.StackLayout({
| |
| expanded: false,
| |
| items: [this.loading, this.defaultPanel, this.ignoredPanel]
| |
| })
| |
| | |
| this.$body.append(this.executing.$element)
| |
| .append(this.saving.$element)
| |
| .append(this.stackLayout.$element);
| |
| };
| |
| | |
| SelectDialog.prototype.createDefaultForm = function() {
| |
| var form = this.defaultForm;
| |
| var auto = false;
| |
| | |
| this.defaultForm.clearItems();
| |
| | |
| var all = new OO.ui.CheckboxInputWidget({
| |
| selected: true
| |
| });
| |
| all.on('change', function(state) {
| |
| if(!auto) {
| |
| auto = true;
| |
| form.items.forEach(function(item) {
| |
| if(item instanceof OO.ui.HorizontalLayout) {
| |
| var checkbox = item.items[0].fieldWidget;
| |
| if(!checkbox.isDisabled()) checkbox.setSelected(state);
| |
| }
| |
| });
| |
| auto = false;
| |
| }
| |
| });
| |
| | |
| this.defaultForm.addItems([
| |
| new OO.ui.FieldLayout(all, {
| |
| label: '모두 선택',
| |
| align: 'inline',
| |
| classes: ['gadgethelper-selectall']
| |
| })
| |
| ]);
| |
| this.defaultForm.addItems(needed.filter(function(gadget) {
| |
| return !ignored.includes(gadget);
| |
| }).map(function(gadget) {
| |
| var ignore = new OO.ui.ButtonWidget({
| |
| classes: ['gadgethelper-ignorebutton'],
| |
| label: '무시',
| |
| flags: 'destructive',
| |
| framed: false
| |
| });
| |
| ignore.on('click', function() {
| |
| ignore.clearFlags();
| |
| if(input.isDisabled()) {
| |
| var index = ignored.indexOf(gadget);
| |
| if(index > -1) ignored.splice(index, 1);
| |
| input.setDisabled(false);
| |
| | |
| if(index > 0) ignoredChanged--;
| |
| | |
| ignore.setLabel('무시');
| |
| ignore.setFlags('destructive');
| |
| } else {
| |
| ignoredChanged++;
| |
| ignored.push(gadget);
| |
| input.setSelected(false);
| |
| input.setDisabled(true);
| |
| | |
| ignore.setLabel('무시 해제');
| |
| ignore.setFlags('progressive');
| |
| }
| |
| });
| |
| | |
| var input = new OO.ui.CheckboxInputWidget({
| |
| name: gadget,
| |
| selected: true,
| |
| classes: ['gadgethelper-checkbox']
| |
| });
| |
| input.on('change', function() {
| |
| if(!auto) {
| |
| auto = true;
| |
| all.setSelected(false);
| |
| auto = false;
| |
| }
| |
| });
| |
| | |
| return new OO.ui.HorizontalLayout({
| |
| classes: ['gadgethelper-item'],
| |
| items: [
| |
| new OO.ui.FieldLayout(input, {
| |
| label: mw.msg('gadget-' + gadget),
| |
| align: 'inline'
| |
| }),
| |
| ignore
| |
| ]
| |
| });
| |
| }));
| |
| };
| |
| | |
| SelectDialog.prototype.getSetupProcess = function(data) {
| |
| var dialog = this;
| |
| | |
| return SelectDialog.super.prototype.getSetupProcess.call(this, data)
| |
| .next(this.waitFor('load', api.loadMessagesIfMissing(needed.map(function(key) {
| |
| return 'gadget-' + key;
| |
| }))))
| |
| .next(function() {
| |
| dialog.createDefaultForm();
| |
| | |
| dialog.stackLayout.setItem(dialog.defaultPanel);
| |
| dialog.actions.setMode('default');
| |
| });
| |
| };
| |
| | |
| SelectDialog.prototype.saveIgnored = function() {
| |
| if(ignoredChanged) {
| |
| ignoredChanged = 0;
| |
| return api.saveOption('userjs-gadgethelper-ignored', ignored.join('|')).then(function() {
| |
| mw.user.options.set('userjs-gadgethelper-ignored', ignored.join('|'));
| |
| | |
| dialog.ignoredForm.clearItems();
| |
| dialog.createDefaultForm();
| |
| });
| |
| } else return Promise.resolve();
| |
| }
| |
| | |
| SelectDialog.prototype.waitFor = function(action, process) {
| |
| var dialog = this;
| |
| this.actions.setMode('wait');
| |
| | |
| switch(action) {
| |
| case 'load':
| |
| this.stackLayout.setItem(this.loading);
| |
| return process;
| |
| break;
| |
| | |
| case 'save':
| |
| this.saving.toggle(true);
| |
| return process.then(function() {
| |
| dialog.saving.toggle(false);
| |
| })
| |
| break;
| |
| | |
| case 'execute':
| |
| this.executing.toggle(true);
| |
| return process.then(function() {
| |
| dialog.executing.toggle(false);
| |
| })
| |
| break;
| |
| | |
| default:
| |
| throw new TypeError('잘못된 동작입니다');
| |
| }
| |
| };
| |
| | |
| SelectDialog.prototype.getActionProcess = function(action) {
| |
| var process = SelectDialog.super.prototype.getActionProcess.call(this, action);
| |
| var dialog = this;
| |
| | |
| switch(action) {
| |
| case 'execute':
| |
| return process
| |
| .next(function() {
| |
| dialog.defaultMessage.toggle(false);
| |
| dialog.defaultForm.items.forEach(function(item) {
| |
| if(item instanceof OO.ui.HorizontalLayout) {
| |
| item.items[0].fieldWidget.setDisabled(true);
| |
| item.items[1].setDisabled(true);
| |
| } else item.fieldWidget.setDisabled(true);
| |
| });
| |
| })
| |
| .next(Promise.all([
| |
| this.waitFor('save', this.saveIgnored()),
| |
| this.waitFor('execute', mw.loader.using(getSelected(this.defaultForm.$element).map(function(gadget) {
| |
| return 'ext.gadget.' + gadget;
| |
| })))
| |
| ]))
| |
| .next(function() {
| |
| dialog.close();
| |
| });
| |
| break;
| |
| | |
| case 'clear':
| |
| return process.next(function() {
| |
| dialog.ignoredMessage.toggle(false);
| |
| dialog.ignoredForm.items.forEach(function(item) {
| |
| if(item instanceof OO.ui.HorizontalLayout) {
| |
| item.items[0].fieldWidget.setDisabled(true);
| |
| item.items[1].setDisabled(true);
| |
| } else item.fieldWidget.setDisabled(true);
| |
| });
| |
|
| |
| ignored = getUnselected(dialog.ignoredForm.$element);
| |
| ignoredChanged = true;
| |
| | |
| return dialog.waitFor('save', dialog.saveIgnored());
| |
| }).next(function() {
| |
| dialog.ignoredMessage.toggle(true);
| |
| dialog.stackLayout.setItem(dialog.defaultPanel);
| |
| dialog.actions.setMode('default');
| |
| });
| |
| break;
| |
|
| |
| case 'close':
| |
| return process.next(function() {
| |
| dialog.defaultMessage.toggle(false);
| |
| dialog.defaultForm.items.forEach(function(item) {
| |
| if(item instanceof OO.ui.HorizontalLayout) {
| |
| item.items[0].fieldWidget.setDisabled(true);
| |
| item.items[1].setDisabled(true);
| |
| } else item.fieldWidget.setDisabled(true);
| |
| });
| |
| }).next(this.waitFor('save', this.saveIgnored())).next(function() {
| |
| dialog.close();
| |
| });
| |
| break;
| |
| | |
| case 'cancel':
| |
| return process.next(function() {
| |
| dialog.stackLayout.setItem(dialog.defaultPanel);
| |
| dialog.actions.setMode('default');
| |
| });
| |
| break;
| |
|
| |
| case 'go-ignored':
| |
| return process.next(Promise.all([
| |
| this.waitFor('save', this.saveIgnored()),
| |
| this.waitFor('load', api.loadMessagesIfMissing(ignored.map(function(key) {
| |
| return 'gadget-' + key;
| |
| })))
| |
| ])).next(function() {
| |
| if(!dialog.ignoredForm.items.length) {
| |
| var all = new OO.ui.CheckboxInputWidget();
| |
| all.on('change', function(checked) {
| |
| dialog.ignoredForm.$element.find('input[type=checkbox]').prop('checked', checked);
| |
| });
| |
| dialog.ignoredForm.addItems([
| |
| new OO.ui.FieldLayout(all, {
| |
| label: '모두 선택',
| |
| align: 'inline'
| |
| })
| |
| ]);
| |
| | |
| dialog.ignoredForm.addItems(ignored.map(function(gadget) {
| |
| return new OO.ui.FieldLayout(new OO.ui.CheckboxInputWidget({
| |
| name: gadget
| |
| }), {
| |
| label: mw.msg('gadget-' + gadget),
| |
| align: 'inline'
| |
| });
| |
| }));
| |
| | |
| }
| |
| | |
| dialog.stackLayout.setItem(dialog.ignoredPanel);
| |
| dialog.actions.setMode('ignored');
| |
| });
| |
| break;
| |
| case 'go-allowed':
| |
| return process.next(function() {
| |
| open('/wiki/%ED%8A%B9%EC%88%98:%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95#mw-prefsection-gadgets');
| |
| });
| |
| break;
| |
| }
| |
| | |
| return process.next(function() {
| |
| throw new TypeError('Wrong action called');
| |
| });
| |
| };
| |
| | |
| SelectDialog.prototype.getBodyHeight = function() {
| |
| return this.stackLayout.currentItem.$element.innerHeight(true);
| |
| };
| |
| | |
| if(needed.length) {
| |
| var windowManager = new OO.ui.WindowManager();
| |
| windowManager.$element.appendTo(document.body);
| |
| | |
| var dialog = new SelectDialog({
| |
| size: 'large'
| |
| });
| |
| windowManager.addWindows([dialog]);
| |
| windowManager.openWindow(dialog);
| |
| }
| |