Refactor client (#3178)
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip
This commit is contained in:
		
							parent
							
								
									5d882dc3df
								
							
						
					
					
						commit
						3f79c9ae49
					
				
					 52 changed files with 328 additions and 421 deletions
				
			
		| 
						 | 
				
			
			@ -1,8 +1,7 @@
 | 
			
		|||
import MiOS from '../../mios';
 | 
			
		||||
import { clientVersion as current } from '../../config';
 | 
			
		||||
 | 
			
		||||
export default async function(mios: MiOS, force = false, silent = false) {
 | 
			
		||||
	const meta = await mios.getMeta(force);
 | 
			
		||||
export default async function($root: any, force = false, silent = false) {
 | 
			
		||||
	const meta = await $root.getMeta(force);
 | 
			
		||||
	const newer = meta.clientVersion;
 | 
			
		||||
 | 
			
		||||
	if (newer != current) {
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +22,7 @@ export default async function(mios: MiOS, force = false, silent = false) {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		if (!silent) {
 | 
			
		||||
			mios.apis.dialog({
 | 
			
		||||
			$root.$dialog({
 | 
			
		||||
				title: '%i18n:common.update-available-title%',
 | 
			
		||||
				text: '%i18n:common.update-available%'.replace('{newer}', newer).replace('{current}', current)
 | 
			
		||||
			});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
declare const fuckAdBlock: any;
 | 
			
		||||
 | 
			
		||||
export default (os) => {
 | 
			
		||||
export default ($root: any) => {
 | 
			
		||||
	require('fuckadblock');
 | 
			
		||||
 | 
			
		||||
	function adBlockDetected() {
 | 
			
		||||
		os.apis.dialog({
 | 
			
		||||
		$root.$dialog({
 | 
			
		||||
			title: '%fa:exclamation-triangle%%i18n:common.adblock.detected%',
 | 
			
		||||
			text: '%i18n:common.adblock.warning%',
 | 
			
		||||
			actins: [{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ export default (opts: Opts = {}) => ({
 | 
			
		|||
 | 
			
		||||
	methods: {
 | 
			
		||||
		reply(viaKeyboard = false) {
 | 
			
		||||
			this.$root.apis.post({
 | 
			
		||||
			this.$root.$post({
 | 
			
		||||
				reply: this.appearNote,
 | 
			
		||||
				animation: !viaKeyboard,
 | 
			
		||||
				cb: () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +98,7 @@ export default (opts: Opts = {}) => ({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		renote(viaKeyboard = false) {
 | 
			
		||||
			this.$root.apis.post({
 | 
			
		||||
			this.$root.$post({
 | 
			
		||||
				renote: this.appearNote,
 | 
			
		||||
				animation: !viaKeyboard,
 | 
			
		||||
				cb: () => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,7 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
	methods: {
 | 
			
		||||
		regenerateToken() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('enter-password'),
 | 
			
		||||
				type: 'password'
 | 
			
		||||
			}).then(password => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -100,7 +100,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		match() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('enter-username')
 | 
			
		||||
			}).then(username => {
 | 
			
		||||
				this.$root.api('users/show', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -131,7 +131,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		chooseFileFromDrive() {
 | 
			
		||||
			this.$root.apis.chooseDriveFile({
 | 
			
		||||
			this.$chooseDriveFile({
 | 
			
		||||
				multiple: false
 | 
			
		||||
			}).then(file => {
 | 
			
		||||
				this.file = file;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,20 +12,20 @@ export default Vue.extend({
 | 
			
		|||
	i18n: i18n('common/views/components/password-settings.vue'),
 | 
			
		||||
	methods: {
 | 
			
		||||
		reset() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('enter-current-password'),
 | 
			
		||||
				type: 'password'
 | 
			
		||||
			}).then(currentPassword => {
 | 
			
		||||
				this.$root.apis.input({
 | 
			
		||||
				this.$input({
 | 
			
		||||
					title: this.$t('enter-new-password'),
 | 
			
		||||
					type: 'password'
 | 
			
		||||
				}).then(newPassword => {
 | 
			
		||||
					this.$root.apis.input({
 | 
			
		||||
					this.$input({
 | 
			
		||||
						title: this.$t('enter-new-password-again'),
 | 
			
		||||
						type: 'password'
 | 
			
		||||
					}).then(newPassword2 => {
 | 
			
		||||
						if (newPassword !== newPassword2) {
 | 
			
		||||
							this.$root.apis.dialog({
 | 
			
		||||
							this.$dialog({
 | 
			
		||||
								title: null,
 | 
			
		||||
								text: this.$t('not-match'),
 | 
			
		||||
								actions: [{
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ export default Vue.extend({
 | 
			
		|||
							currentPasword: currentPassword,
 | 
			
		||||
							newPassword: newPassword
 | 
			
		||||
						}).then(() => {
 | 
			
		||||
							this.$root.apis.notify(this.$t('changed'));
 | 
			
		||||
							this.$notify(this.$t('changed'));
 | 
			
		||||
						});
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ export default define({
 | 
			
		|||
			});
 | 
			
		||||
		},
 | 
			
		||||
		choose() {
 | 
			
		||||
			this.$root.apis.chooseDriveFolder().then(folder => {
 | 
			
		||||
			this.$chooseDriveFolder().then(folder => {
 | 
			
		||||
				this.props.folder = folder ? folder.id : null;
 | 
			
		||||
				this.save();
 | 
			
		||||
				this.fetch();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,29 +0,0 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import { url } from '../../config';
 | 
			
		||||
import MkChooseFileFromDriveWindow from '../views/components/choose-file-from-drive-window.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => opts => {
 | 
			
		||||
	return new Promise((res, rej) => {
 | 
			
		||||
		const o = opts || {};
 | 
			
		||||
 | 
			
		||||
		if (document.body.clientWidth > 800) {
 | 
			
		||||
			const w = os.new(MkChooseFileFromDriveWindow, {
 | 
			
		||||
				title: o.title,
 | 
			
		||||
				multiple: o.multiple,
 | 
			
		||||
				initFolder: o.currentFolder
 | 
			
		||||
			});
 | 
			
		||||
			w.$once('selected', file => {
 | 
			
		||||
				res(file);
 | 
			
		||||
			});
 | 
			
		||||
			document.body.appendChild(w.$el);
 | 
			
		||||
		} else {
 | 
			
		||||
			window['cb'] = file => {
 | 
			
		||||
				res(file);
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			window.open(url + `/selectdrive?multiple=${o.multiple}`,
 | 
			
		||||
				'choose_drive_window',
 | 
			
		||||
				'height=500, width=800');
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,16 +0,0 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import MkChooseFolderFromDriveWindow from '../views/components/choose-folder-from-drive-window.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => opts => {
 | 
			
		||||
	return new Promise((res, rej) => {
 | 
			
		||||
		const o = opts || {};
 | 
			
		||||
		const w = os.new(MkChooseFolderFromDriveWindow, {
 | 
			
		||||
			title: o.title,
 | 
			
		||||
			initFolder: o.currentFolder
 | 
			
		||||
		});
 | 
			
		||||
		w.$once('selected', folder => {
 | 
			
		||||
			res(folder);
 | 
			
		||||
		});
 | 
			
		||||
		document.body.appendChild(w.$el);
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import Ctx from '../views/components/context-menu.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => (e, menu, opts?) => {
 | 
			
		||||
	const o = opts || {};
 | 
			
		||||
	const vm = os.new(Ctx, {
 | 
			
		||||
		menu,
 | 
			
		||||
		x: e.pageX - window.pageXOffset,
 | 
			
		||||
		y: e.pageY - window.pageYOffset,
 | 
			
		||||
	});
 | 
			
		||||
	vm.$once('closed', () => {
 | 
			
		||||
		if (o.closed) o.closed();
 | 
			
		||||
	});
 | 
			
		||||
	document.body.appendChild(vm.$el);
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import Dialog from '../views/components/dialog.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => opts => {
 | 
			
		||||
	return new Promise<string>((res, rej) => {
 | 
			
		||||
		const o = opts || {};
 | 
			
		||||
		const d = os.new(Dialog, {
 | 
			
		||||
			title: o.title,
 | 
			
		||||
			text: o.text,
 | 
			
		||||
			modal: o.modal,
 | 
			
		||||
			buttons: o.actions
 | 
			
		||||
		});
 | 
			
		||||
		d.$once('clicked', id => {
 | 
			
		||||
			res(id);
 | 
			
		||||
		});
 | 
			
		||||
		document.body.appendChild(d.$el);
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,19 +0,0 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import InputDialog from '../views/components/input-dialog.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => opts => {
 | 
			
		||||
	return new Promise<string>((res, rej) => {
 | 
			
		||||
		const o = opts || {};
 | 
			
		||||
		const d = os.new(InputDialog, {
 | 
			
		||||
			title: o.title,
 | 
			
		||||
			placeholder: o.placeholder,
 | 
			
		||||
			default: o.default,
 | 
			
		||||
			type: o.type || 'text',
 | 
			
		||||
			allowEmpty: o.allowEmpty
 | 
			
		||||
		});
 | 
			
		||||
		d.$once('done', text => {
 | 
			
		||||
			res(text);
 | 
			
		||||
		});
 | 
			
		||||
		document.body.appendChild(d.$el);
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +0,0 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import Notification from '../views/components/ui-notification.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => message => {
 | 
			
		||||
	const vm = os.new(Notification, {
 | 
			
		||||
		message
 | 
			
		||||
	});
 | 
			
		||||
	document.body.appendChild(vm.$el);
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,22 +0,0 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import PostFormWindow from '../views/components/post-form-window.vue';
 | 
			
		||||
import RenoteFormWindow from '../views/components/renote-form-window.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => opts => {
 | 
			
		||||
	const o = opts || {};
 | 
			
		||||
	if (o.renote) {
 | 
			
		||||
		const vm = os.new(RenoteFormWindow, {
 | 
			
		||||
			note: o.renote,
 | 
			
		||||
			animation: o.animation == null ? true : o.animation
 | 
			
		||||
		});
 | 
			
		||||
		if (o.cb) vm.$once('closed', o.cb);
 | 
			
		||||
		document.body.appendChild(vm.$el);
 | 
			
		||||
	} else {
 | 
			
		||||
		const vm = os.new(PostFormWindow, {
 | 
			
		||||
			reply: o.reply,
 | 
			
		||||
			animation: o.animation == null ? true : o.animation
 | 
			
		||||
		});
 | 
			
		||||
		if (o.cb) vm.$once('closed', o.cb);
 | 
			
		||||
		document.body.appendChild(vm.$el);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +1,14 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import { apiUrl } from '../../config';
 | 
			
		||||
import CropWindow from '../views/components/crop-window.vue';
 | 
			
		||||
import ProgressDialog from '../views/components/progress-dialog.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => {
 | 
			
		||||
export default ($root: any) => {
 | 
			
		||||
 | 
			
		||||
	const cropImage = file => new Promise((resolve, reject) => {
 | 
			
		||||
 | 
			
		||||
		const regex = RegExp('\.(jpg|jpeg|png|gif|webp|bmp|tiff)$');
 | 
			
		||||
		if (!regex.test(file.name) ) {
 | 
			
		||||
			os.apis.dialog({
 | 
			
		||||
			$root.$dialog({
 | 
			
		||||
				title: '%fa:info-circle% %i18n:desktop.invalid-filetype%',
 | 
			
		||||
				text: null,
 | 
			
		||||
				actions: [{
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +18,7 @@ export default (os: OS) => {
 | 
			
		|||
			return reject('invalid-filetype');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const w = os.new(CropWindow, {
 | 
			
		||||
		const w = $root.new(CropWindow, {
 | 
			
		||||
			image: file,
 | 
			
		||||
			title: '%i18n:desktop.avatar-crop-title%',
 | 
			
		||||
			aspectRatio: 1 / 1
 | 
			
		||||
| 
						 | 
				
			
			@ -27,14 +26,14 @@ export default (os: OS) => {
 | 
			
		|||
 | 
			
		||||
		w.$once('cropped', blob => {
 | 
			
		||||
			const data = new FormData();
 | 
			
		||||
			data.append('i', os.store.state.i.token);
 | 
			
		||||
			data.append('i', $root.$store.state.i.token);
 | 
			
		||||
			data.append('file', blob, file.name + '.cropped.png');
 | 
			
		||||
 | 
			
		||||
			os.api('drive/folders/find', {
 | 
			
		||||
			$root.api('drive/folders/find', {
 | 
			
		||||
				name: '%i18n:desktop.avatar%'
 | 
			
		||||
			}).then(avatarFolder => {
 | 
			
		||||
				if (avatarFolder.length === 0) {
 | 
			
		||||
					os.api('drive/folders/create', {
 | 
			
		||||
					$root.api('drive/folders/create', {
 | 
			
		||||
						name: '%i18n:desktop.avatar%'
 | 
			
		||||
					}).then(iconFolder => {
 | 
			
		||||
						resolve(upload(data, iconFolder));
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +54,7 @@ export default (os: OS) => {
 | 
			
		|||
	});
 | 
			
		||||
 | 
			
		||||
	const upload = (data, folder) => new Promise((resolve, reject) => {
 | 
			
		||||
		const dialog = os.new(ProgressDialog, {
 | 
			
		||||
		const dialog = $root.new(ProgressDialog, {
 | 
			
		||||
			title: '%i18n:desktop.uploading-avatar%'
 | 
			
		||||
		});
 | 
			
		||||
		document.body.appendChild(dialog.$el);
 | 
			
		||||
| 
						 | 
				
			
			@ -79,19 +78,19 @@ export default (os: OS) => {
 | 
			
		|||
	});
 | 
			
		||||
 | 
			
		||||
	const setAvatar = file => {
 | 
			
		||||
		return os.api('i/update', {
 | 
			
		||||
		return $root.api('i/update', {
 | 
			
		||||
			avatarId: file.id
 | 
			
		||||
		}).then(i => {
 | 
			
		||||
			os.store.commit('updateIKeyValue', {
 | 
			
		||||
			$root.$store.commit('updateIKeyValue', {
 | 
			
		||||
				key: 'avatarId',
 | 
			
		||||
				value: i.avatarId
 | 
			
		||||
			});
 | 
			
		||||
			os.store.commit('updateIKeyValue', {
 | 
			
		||||
			$root.$store.commit('updateIKeyValue', {
 | 
			
		||||
				key: 'avatarUrl',
 | 
			
		||||
				value: i.avatarUrl
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			os.apis.dialog({
 | 
			
		||||
			$root.$dialog({
 | 
			
		||||
				title: '%fa:info-circle% %i18n:desktop.avatar-updated%',
 | 
			
		||||
				text: null,
 | 
			
		||||
				actions: [{
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +105,7 @@ export default (os: OS) => {
 | 
			
		|||
	return (file = null) => {
 | 
			
		||||
		const selectedFile = file
 | 
			
		||||
			? Promise.resolve(file)
 | 
			
		||||
			: os.apis.chooseDriveFile({
 | 
			
		||||
			: $root.$chooseDriveFile({
 | 
			
		||||
				multiple: false,
 | 
			
		||||
				title: '%fa:image% %i18n:desktop.choose-avatar%'
 | 
			
		||||
			});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,14 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import { apiUrl } from '../../config';
 | 
			
		||||
import CropWindow from '../views/components/crop-window.vue';
 | 
			
		||||
import ProgressDialog from '../views/components/progress-dialog.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => {
 | 
			
		||||
export default ($root: any) => {
 | 
			
		||||
 | 
			
		||||
	const cropImage = file => new Promise((resolve, reject) => {
 | 
			
		||||
 | 
			
		||||
		const regex = RegExp('\.(jpg|jpeg|png|gif|webp|bmp|tiff)$');
 | 
			
		||||
		if (!regex.test(file.name) ) {
 | 
			
		||||
			os.apis.dialog({
 | 
			
		||||
			$root.dialog({
 | 
			
		||||
				title: '%fa:info-circle% %i18n:desktop.invalid-filetype%',
 | 
			
		||||
				text: null,
 | 
			
		||||
				actions: [{
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +18,7 @@ export default (os: OS) => {
 | 
			
		|||
			return reject('invalid-filetype');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const w = os.new(CropWindow, {
 | 
			
		||||
		const w = $root.new(CropWindow, {
 | 
			
		||||
			image: file,
 | 
			
		||||
			title: '%i18n:desktop.banner-crop-title%',
 | 
			
		||||
			aspectRatio: 16 / 9
 | 
			
		||||
| 
						 | 
				
			
			@ -27,14 +26,14 @@ export default (os: OS) => {
 | 
			
		|||
 | 
			
		||||
		w.$once('cropped', blob => {
 | 
			
		||||
			const data = new FormData();
 | 
			
		||||
			data.append('i', os.store.state.i.token);
 | 
			
		||||
			data.append('i', $root.$store.state.i.token);
 | 
			
		||||
			data.append('file', blob, file.name + '.cropped.png');
 | 
			
		||||
 | 
			
		||||
			os.api('drive/folders/find', {
 | 
			
		||||
			$root.api('drive/folders/find', {
 | 
			
		||||
				name: '%i18n:desktop.banner%'
 | 
			
		||||
			}).then(bannerFolder => {
 | 
			
		||||
				if (bannerFolder.length === 0) {
 | 
			
		||||
					os.api('drive/folders/create', {
 | 
			
		||||
					$root.api('drive/folders/create', {
 | 
			
		||||
						name: '%i18n:desktop.banner%'
 | 
			
		||||
					}).then(iconFolder => {
 | 
			
		||||
						resolve(upload(data, iconFolder));
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +54,7 @@ export default (os: OS) => {
 | 
			
		|||
	});
 | 
			
		||||
 | 
			
		||||
	const upload = (data, folder) => new Promise((resolve, reject) => {
 | 
			
		||||
		const dialog = os.new(ProgressDialog, {
 | 
			
		||||
		const dialog = $root.new(ProgressDialog, {
 | 
			
		||||
			title: '%i18n:desktop.uploading-banner%'
 | 
			
		||||
		});
 | 
			
		||||
		document.body.appendChild(dialog.$el);
 | 
			
		||||
| 
						 | 
				
			
			@ -79,19 +78,19 @@ export default (os: OS) => {
 | 
			
		|||
	});
 | 
			
		||||
 | 
			
		||||
	const setBanner = file => {
 | 
			
		||||
		return os.api('i/update', {
 | 
			
		||||
		return $root.api('i/update', {
 | 
			
		||||
			bannerId: file.id
 | 
			
		||||
		}).then(i => {
 | 
			
		||||
			os.store.commit('updateIKeyValue', {
 | 
			
		||||
			$root.$store.commit('updateIKeyValue', {
 | 
			
		||||
				key: 'bannerId',
 | 
			
		||||
				value: i.bannerId
 | 
			
		||||
			});
 | 
			
		||||
			os.store.commit('updateIKeyValue', {
 | 
			
		||||
			$root.$store.commit('updateIKeyValue', {
 | 
			
		||||
				key: 'bannerUrl',
 | 
			
		||||
				value: i.bannerUrl
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			os.apis.dialog({
 | 
			
		||||
			$root.$dialog({
 | 
			
		||||
				title: '%fa:info-circle% %i18n:desktop.banner-updated%',
 | 
			
		||||
				text: null,
 | 
			
		||||
				actions: [{
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +105,7 @@ export default (os: OS) => {
 | 
			
		|||
	return (file = null) => {
 | 
			
		||||
		const selectedFile = file
 | 
			
		||||
			? Promise.resolve(file)
 | 
			
		||||
			: os.apis.chooseDriveFile({
 | 
			
		||||
			: $root.$chooseDriveFile({
 | 
			
		||||
				multiple: false,
 | 
			
		||||
				title: '%fa:image% %i18n:desktop.choose-banner%'
 | 
			
		||||
			});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
 * Desktop Client
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
import VueRouter from 'vue-router';
 | 
			
		||||
 | 
			
		||||
// Style
 | 
			
		||||
| 
						 | 
				
			
			@ -11,15 +12,6 @@ import init from '../init';
 | 
			
		|||
import fuckAdBlock from '../common/scripts/fuck-ad-block';
 | 
			
		||||
import composeNotification from '../common/scripts/compose-notification';
 | 
			
		||||
 | 
			
		||||
import chooseDriveFolder from './api/choose-drive-folder';
 | 
			
		||||
import chooseDriveFile from './api/choose-drive-file';
 | 
			
		||||
import dialog from './api/dialog';
 | 
			
		||||
import input from './api/input';
 | 
			
		||||
import post from './api/post';
 | 
			
		||||
import notify from './api/notify';
 | 
			
		||||
import updateAvatar from './api/update-avatar';
 | 
			
		||||
import updateBanner from './api/update-banner';
 | 
			
		||||
 | 
			
		||||
import MkIndex from './views/pages/index.vue';
 | 
			
		||||
import MkHome from './views/pages/home.vue';
 | 
			
		||||
import MkDeck from './views/pages/deck/deck.vue';
 | 
			
		||||
| 
						 | 
				
			
			@ -36,12 +28,131 @@ import MkTag from './views/pages/tag.vue';
 | 
			
		|||
import MkReversi from './views/pages/games/reversi.vue';
 | 
			
		||||
import MkShare from './views/pages/share.vue';
 | 
			
		||||
import MkFollow from '../common/views/pages/follow.vue';
 | 
			
		||||
 | 
			
		||||
import Ctx from './views/components/context-menu.vue';
 | 
			
		||||
import PostFormWindow from './views/components/post-form-window.vue';
 | 
			
		||||
import RenoteFormWindow from './views/components/renote-form-window.vue';
 | 
			
		||||
import MkChooseFileFromDriveWindow from './views/components/choose-file-from-drive-window.vue';
 | 
			
		||||
import MkChooseFolderFromDriveWindow from './views/components/choose-folder-from-drive-window.vue';
 | 
			
		||||
import Dialog from './views/components/dialog.vue';
 | 
			
		||||
import InputDialog from './views/components/input-dialog.vue';
 | 
			
		||||
import Notification from './views/components/ui-notification.vue';
 | 
			
		||||
 | 
			
		||||
import { url } from '../config';
 | 
			
		||||
import MiOS from '../mios';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * init
 | 
			
		||||
 */
 | 
			
		||||
init(async (launch) => {
 | 
			
		||||
	Vue.mixin({
 | 
			
		||||
		methods: {
 | 
			
		||||
			$contextmenu(e, menu, opts?) {
 | 
			
		||||
				const o = opts || {};
 | 
			
		||||
				const vm = this.$root.new(Ctx, {
 | 
			
		||||
					menu,
 | 
			
		||||
					x: e.pageX - window.pageXOffset,
 | 
			
		||||
					y: e.pageY - window.pageYOffset,
 | 
			
		||||
				});
 | 
			
		||||
				vm.$once('closed', () => {
 | 
			
		||||
					if (o.closed) o.closed();
 | 
			
		||||
				});
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$post(opts) {
 | 
			
		||||
				const o = opts || {};
 | 
			
		||||
				if (o.renote) {
 | 
			
		||||
					const vm = this.$root.new(RenoteFormWindow, {
 | 
			
		||||
						note: o.renote,
 | 
			
		||||
						animation: o.animation == null ? true : o.animation
 | 
			
		||||
					});
 | 
			
		||||
					if (o.cb) vm.$once('closed', o.cb);
 | 
			
		||||
				} else {
 | 
			
		||||
					const vm = this.$root.new(PostFormWindow, {
 | 
			
		||||
						reply: o.reply,
 | 
			
		||||
						animation: o.animation == null ? true : o.animation
 | 
			
		||||
					});
 | 
			
		||||
					if (o.cb) vm.$once('closed', o.cb);
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$chooseDriveFile(opts) {
 | 
			
		||||
				return new Promise((res, rej) => {
 | 
			
		||||
					const o = opts || {};
 | 
			
		||||
 | 
			
		||||
					if (document.body.clientWidth > 800) {
 | 
			
		||||
						const w = this.$root.new(MkChooseFileFromDriveWindow, {
 | 
			
		||||
							title: o.title,
 | 
			
		||||
							multiple: o.multiple,
 | 
			
		||||
							initFolder: o.currentFolder
 | 
			
		||||
						});
 | 
			
		||||
						w.$once('selected', file => {
 | 
			
		||||
							res(file);
 | 
			
		||||
						});
 | 
			
		||||
					} else {
 | 
			
		||||
						window['cb'] = file => {
 | 
			
		||||
							res(file);
 | 
			
		||||
						};
 | 
			
		||||
 | 
			
		||||
						window.open(url + `/selectdrive?multiple=${o.multiple}`,
 | 
			
		||||
							'choose_drive_window',
 | 
			
		||||
							'height=500, width=800');
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$chooseDriveFolder(opts) {
 | 
			
		||||
				return new Promise((res, rej) => {
 | 
			
		||||
					const o = opts || {};
 | 
			
		||||
					const w = this.$root.new(MkChooseFolderFromDriveWindow, {
 | 
			
		||||
						title: o.title,
 | 
			
		||||
						initFolder: o.currentFolder
 | 
			
		||||
					});
 | 
			
		||||
					w.$once('selected', folder => {
 | 
			
		||||
						res(folder);
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$dialog(opts) {
 | 
			
		||||
				return new Promise<string>((res, rej) => {
 | 
			
		||||
					const o = opts || {};
 | 
			
		||||
					const d = this.$root.new(Dialog, {
 | 
			
		||||
						title: o.title,
 | 
			
		||||
						text: o.text,
 | 
			
		||||
						modal: o.modal,
 | 
			
		||||
						buttons: o.actions
 | 
			
		||||
					});
 | 
			
		||||
					d.$once('clicked', id => {
 | 
			
		||||
						res(id);
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$input(opts) {
 | 
			
		||||
				return new Promise<string>((res, rej) => {
 | 
			
		||||
					const o = opts || {};
 | 
			
		||||
					const d = this.$root.new(InputDialog, {
 | 
			
		||||
						title: o.title,
 | 
			
		||||
						placeholder: o.placeholder,
 | 
			
		||||
						default: o.default,
 | 
			
		||||
						type: o.type || 'text',
 | 
			
		||||
						allowEmpty: o.allowEmpty
 | 
			
		||||
					});
 | 
			
		||||
					d.$once('done', text => {
 | 
			
		||||
						res(text);
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$notify(message) {
 | 
			
		||||
				this.$root.new(Notification, {
 | 
			
		||||
					message
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	// Register directives
 | 
			
		||||
	require('./views/directives');
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -75,22 +186,13 @@ init(async (launch) => {
 | 
			
		|||
	});
 | 
			
		||||
 | 
			
		||||
	// Launch the app
 | 
			
		||||
	const [, os] = launch(router, os => ({
 | 
			
		||||
		chooseDriveFolder: chooseDriveFolder(os),
 | 
			
		||||
		chooseDriveFile: chooseDriveFile(os),
 | 
			
		||||
		dialog: dialog(os),
 | 
			
		||||
		input: input(os),
 | 
			
		||||
		post: post(os),
 | 
			
		||||
		notify: notify(os),
 | 
			
		||||
		updateAvatar: updateAvatar(os),
 | 
			
		||||
		updateBanner: updateBanner(os)
 | 
			
		||||
	}));
 | 
			
		||||
	const [app, os] = launch(router);
 | 
			
		||||
 | 
			
		||||
	if (os.store.getters.isSignedIn) {
 | 
			
		||||
		/**
 | 
			
		||||
		 * Fuck AD Block
 | 
			
		||||
		 */
 | 
			
		||||
		fuckAdBlock(os);
 | 
			
		||||
		fuckAdBlock(app);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,6 @@
 | 
			
		|||
import Vue from 'vue';
 | 
			
		||||
import i18n from '../../../i18n';
 | 
			
		||||
import * as anime from 'animejs';
 | 
			
		||||
import contextmenu from '../../api/contextmenu';
 | 
			
		||||
import copyToClipboard from '../../../common/scripts/copy-to-clipboard';
 | 
			
		||||
 | 
			
		||||
export default Vue.extend({
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +69,7 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
		onContextmenu(e) {
 | 
			
		||||
			this.isContextmenuShowing = true;
 | 
			
		||||
			contextmenu((this as any).os)(e, [{
 | 
			
		||||
			this.$contextmenu(e, [{
 | 
			
		||||
				type: 'item',
 | 
			
		||||
				text: this.$t('contextmenu.rename'),
 | 
			
		||||
				icon: 'i-cursor',
 | 
			
		||||
| 
						 | 
				
			
			@ -149,7 +148,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		rename() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('contextmenu.rename-file'),
 | 
			
		||||
				placeholder: this.$t('contextmenu.input-new-file-name'),
 | 
			
		||||
				default: this.file.name,
 | 
			
		||||
| 
						 | 
				
			
			@ -171,7 +170,7 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
		copyUrl() {
 | 
			
		||||
			copyToClipboard(this.file.url);
 | 
			
		||||
			this.$root.apis.dialog({
 | 
			
		||||
			this.$dialog({
 | 
			
		||||
				title: this.$t('contextmenu.copied'),
 | 
			
		||||
				text: this.$t('contextmenu.copied-url-to-clipboard'),
 | 
			
		||||
				actions: [{
 | 
			
		||||
| 
						 | 
				
			
			@ -181,11 +180,11 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		setAsAvatar() {
 | 
			
		||||
			this.$root.apis.updateAvatar(this.file);
 | 
			
		||||
			this.$updateAvatar(this.file);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		setAsBanner() {
 | 
			
		||||
			this.$root.apis.updateBanner(this.file);
 | 
			
		||||
			this.$updateBanner(this.file);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		addApp() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,6 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
import i18n from '../../../i18n';
 | 
			
		||||
import contextmenu from '../../api/contextmenu';
 | 
			
		||||
 | 
			
		||||
export default Vue.extend({
 | 
			
		||||
	i18n: i18n('desktop/views/components/drive.folder.vue'),
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +53,7 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
		onContextmenu(e) {
 | 
			
		||||
			this.isContextmenuShowing = true;
 | 
			
		||||
			contextmenu((this as any).os)(e, [{
 | 
			
		||||
			this.$contextmenu(e, [{
 | 
			
		||||
				type: 'item',
 | 
			
		||||
				text: this.$t('contextmenu.move-to-this-folder'),
 | 
			
		||||
				icon: 'arrow-right',
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +155,7 @@ export default Vue.extend({
 | 
			
		|||
				}).catch(err => {
 | 
			
		||||
					switch (err) {
 | 
			
		||||
						case 'detected-circular-definition':
 | 
			
		||||
							this.$root.apis.dialog({
 | 
			
		||||
							this.$dialog({
 | 
			
		||||
								title: this.$t('unable-to-process'),
 | 
			
		||||
								text: this.$t('circular-reference-detected'),
 | 
			
		||||
								actions: [{
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +195,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		rename() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('contextmenu.rename-folder'),
 | 
			
		||||
				placeholder: this.$t('contextmenu.input-new-folder-name'),
 | 
			
		||||
				default: this.folder.name
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,7 +65,6 @@ import XNavFolder from './drive.nav-folder.vue';
 | 
			
		|||
import XFolder from './drive.folder.vue';
 | 
			
		||||
import XFile from './drive.file.vue';
 | 
			
		||||
import contains from '../../../common/scripts/contains';
 | 
			
		||||
import contextmenu from '../../api/contextmenu';
 | 
			
		||||
import { url } from '../../../config';
 | 
			
		||||
 | 
			
		||||
export default Vue.extend({
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +136,7 @@ export default Vue.extend({
 | 
			
		|||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		onContextmenu(e) {
 | 
			
		||||
			contextmenu((this as any).os)(e, [{
 | 
			
		||||
			this.$contextmenu(e, [{
 | 
			
		||||
				type: 'item',
 | 
			
		||||
				text: this.$t('contextmenu.create-folder'),
 | 
			
		||||
				icon: ['far', 'folder'],
 | 
			
		||||
| 
						 | 
				
			
			@ -314,7 +313,7 @@ export default Vue.extend({
 | 
			
		|||
				}).catch(err => {
 | 
			
		||||
					switch (err) {
 | 
			
		||||
						case 'detected-circular-definition':
 | 
			
		||||
							this.$root.apis.dialog({
 | 
			
		||||
							this.$dialog({
 | 
			
		||||
								title: this.$t('unable-to-process'),
 | 
			
		||||
								text: this.$t('circular-reference-detected'),
 | 
			
		||||
								actions: [{
 | 
			
		||||
| 
						 | 
				
			
			@ -335,7 +334,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		urlUpload() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('url-upload'),
 | 
			
		||||
				placeholder: this.$t('url-of-file')
 | 
			
		||||
			}).then(url => {
 | 
			
		||||
| 
						 | 
				
			
			@ -344,7 +343,7 @@ export default Vue.extend({
 | 
			
		|||
					folderId: this.folder ? this.folder.id : undefined
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				this.$root.apis.dialog({
 | 
			
		||||
				this.$dialog({
 | 
			
		||||
					title: this.$t('url-upload-requested'),
 | 
			
		||||
					text: this.$t('may-take-time'),
 | 
			
		||||
					actions: [{
 | 
			
		||||
| 
						 | 
				
			
			@ -355,7 +354,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		createFolder() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('create-folder'),
 | 
			
		||||
				placeholder: this.$t('folder-name')
 | 
			
		||||
			}).then(name => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -186,7 +186,7 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
	methods: {
 | 
			
		||||
		hint() {
 | 
			
		||||
			this.$root.apis.dialog({
 | 
			
		||||
			this.$dialog({
 | 
			
		||||
				title: this.$t('@.customization-tips.title'),
 | 
			
		||||
				text: this.$t('@.customization-tips.paragraph'),
 | 
			
		||||
				actions: [{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -245,7 +245,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		chooseFileFromDrive() {
 | 
			
		||||
			this.$root.apis.chooseDriveFile({
 | 
			
		||||
			this.$chooseDriveFile({
 | 
			
		||||
				multiple: true
 | 
			
		||||
			}).then(files => {
 | 
			
		||||
				files.forEach(this.attachMedia);
 | 
			
		||||
| 
						 | 
				
			
			@ -363,7 +363,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		addVisibleUser() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('enter-username')
 | 
			
		||||
			}).then(acct => {
 | 
			
		||||
				if (acct.startsWith('@')) acct = acct.substr(1);
 | 
			
		||||
| 
						 | 
				
			
			@ -401,13 +401,13 @@ export default Vue.extend({
 | 
			
		|||
				this.clear();
 | 
			
		||||
				this.deleteDraft();
 | 
			
		||||
				this.$emit('posted');
 | 
			
		||||
				this.$root.apis.notify(this.renote
 | 
			
		||||
				this.$notify(this.renote
 | 
			
		||||
					? this.$t('reposted')
 | 
			
		||||
					: this.reply
 | 
			
		||||
						? this.$t('replied')
 | 
			
		||||
						: this.$t('posted'));
 | 
			
		||||
			}).catch(err => {
 | 
			
		||||
				this.$root.apis.notify(this.renote
 | 
			
		||||
				this.$notify(this.renote
 | 
			
		||||
					? this.$t('renote-failed')
 | 
			
		||||
					: this.reply
 | 
			
		||||
						? this.$t('reply-failed')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,9 +34,9 @@ export default Vue.extend({
 | 
			
		|||
				renoteId: this.note.id
 | 
			
		||||
			}).then(data => {
 | 
			
		||||
				this.$emit('posted');
 | 
			
		||||
				this.$root.apis.notify(this.$t('success'));
 | 
			
		||||
				this.$notify(this.$t('success'));
 | 
			
		||||
			}).catch(err => {
 | 
			
		||||
				this.$root.apis.notify(this.$t('failure'));
 | 
			
		||||
				this.$notify(this.$t('failure'));
 | 
			
		||||
			}).then(() => {
 | 
			
		||||
				this.wait = false;
 | 
			
		||||
			});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ export default Vue.extend({
 | 
			
		|||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		register() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('enter-password'),
 | 
			
		||||
				type: 'password'
 | 
			
		||||
			}).then(password => {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,14 +48,14 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		unregister() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('enter-password'),
 | 
			
		||||
				type: 'password'
 | 
			
		||||
			}).then(password => {
 | 
			
		||||
				this.$root.api('i/2fa/unregister', {
 | 
			
		||||
					password: password
 | 
			
		||||
				}).then(() => {
 | 
			
		||||
					this.$root.apis.notify(this.$t('unregistered'));
 | 
			
		||||
					this.$notify(this.$t('unregistered'));
 | 
			
		||||
					this.$store.state.i.twoFactorEnabled = false;
 | 
			
		||||
				});
 | 
			
		||||
			});
 | 
			
		||||
| 
						 | 
				
			
			@ -65,10 +65,10 @@ export default Vue.extend({
 | 
			
		|||
			this.$root.api('i/2fa/done', {
 | 
			
		||||
				token: this.token
 | 
			
		||||
			}).then(() => {
 | 
			
		||||
				this.$root.apis.notify(this.$t('success'));
 | 
			
		||||
				this.$notify(this.$t('success'));
 | 
			
		||||
				this.$store.state.i.twoFactorEnabled = true;
 | 
			
		||||
			}).catch(() => {
 | 
			
		||||
				this.$root.apis.notify(this.$t('failed'));
 | 
			
		||||
				this.$notify(this.$t('failed'));
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -513,7 +513,7 @@ export default Vue.extend({
 | 
			
		|||
			this.$emit('done');
 | 
			
		||||
		},
 | 
			
		||||
		updateWallpaper() {
 | 
			
		||||
			this.$root.apis.chooseDriveFile({
 | 
			
		||||
			this.$chooseDriveFile({
 | 
			
		||||
				multiple: false
 | 
			
		||||
			}).then(file => {
 | 
			
		||||
				this.$root.api('i/update', {
 | 
			
		||||
| 
						 | 
				
			
			@ -533,16 +533,16 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
		checkForUpdate() {
 | 
			
		||||
			this.checkingForUpdate = true;
 | 
			
		||||
			checkForUpdate((this as any).os, true, true).then(newer => {
 | 
			
		||||
			checkForUpdate(this.$root, true, true).then(newer => {
 | 
			
		||||
				this.checkingForUpdate = false;
 | 
			
		||||
				this.latestVersion = newer;
 | 
			
		||||
				if (newer == null) {
 | 
			
		||||
					this.$root.apis.dialog({
 | 
			
		||||
					this.$dialog({
 | 
			
		||||
						title: this.$t('no-updates'),
 | 
			
		||||
						text: this.$t('no-updates-desc')
 | 
			
		||||
					});
 | 
			
		||||
				} else {
 | 
			
		||||
					this.$root.apis.dialog({
 | 
			
		||||
					this.$dialog({
 | 
			
		||||
						title: this.$t('update-available'),
 | 
			
		||||
						text: this.$t('update-available-desc')
 | 
			
		||||
					});
 | 
			
		||||
| 
						 | 
				
			
			@ -551,7 +551,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
		clean() {
 | 
			
		||||
			localStorage.clear();
 | 
			
		||||
			this.$root.apis.dialog({
 | 
			
		||||
			this.$dialog({
 | 
			
		||||
				title: this.$t('cache-cleared'),
 | 
			
		||||
				text: this.$t('cache-cleared-desc')
 | 
			
		||||
			});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,7 +109,7 @@ export default Vue.extend({
 | 
			
		|||
				icon: 'plus',
 | 
			
		||||
				text: this.$t('add-list'),
 | 
			
		||||
				action: () => {
 | 
			
		||||
					this.$root.apis.input({
 | 
			
		||||
					this.$input({
 | 
			
		||||
						title: this.$t('list-name'),
 | 
			
		||||
					}).then(async title => {
 | 
			
		||||
						const list = await this.$root.api('users/lists/create', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ export default Vue.extend({
 | 
			
		|||
	i18n: i18n('desktop/views/components/ui.header.post.vue'),
 | 
			
		||||
	methods: {
 | 
			
		||||
		post() {
 | 
			
		||||
			this.$root.apis.post();
 | 
			
		||||
			this.$post();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -139,7 +139,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		post() {
 | 
			
		||||
			this.$root.apis.post();
 | 
			
		||||
			this.$post();
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		drive() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
	methods: {
 | 
			
		||||
		post() {
 | 
			
		||||
			this.$root.apis.post();
 | 
			
		||||
			this.$post();
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		toggleZenMode() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ export default Vue.extend({
 | 
			
		|||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		add() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('list-name'),
 | 
			
		||||
			}).then(async title => {
 | 
			
		||||
				const list = await this.$root.api('users/lists/create', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,6 @@
 | 
			
		|||
import Vue from 'vue';
 | 
			
		||||
import i18n from '../../../../i18n';
 | 
			
		||||
import Menu from '../../../../common/views/components/menu.vue';
 | 
			
		||||
import contextmenu from '../../../api/contextmenu';
 | 
			
		||||
import { countIf } from '../../../../../../prelude/array';
 | 
			
		||||
 | 
			
		||||
export default Vue.extend({
 | 
			
		||||
| 
						 | 
				
			
			@ -168,7 +167,7 @@ export default Vue.extend({
 | 
			
		|||
				icon: 'pencil-alt',
 | 
			
		||||
				text: this.$t('rename'),
 | 
			
		||||
				action: () => {
 | 
			
		||||
					this.$root.apis.input({
 | 
			
		||||
					this.$input({
 | 
			
		||||
						title: this.$t('rename'),
 | 
			
		||||
						default: this.name,
 | 
			
		||||
						allowEmpty: false
 | 
			
		||||
| 
						 | 
				
			
			@ -230,7 +229,7 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
		onContextmenu(e) {
 | 
			
		||||
			if (this.isTemporaryColumn) return;
 | 
			
		||||
			contextmenu((this as any).os)(e, this.getMenu());
 | 
			
		||||
			this.$contextmenu(e, this.getMenu());
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		showMenu() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -255,7 +255,7 @@ export default Vue.extend({
 | 
			
		|||
					icon: 'hashtag',
 | 
			
		||||
					text: this.$t('@deck.hashtag'),
 | 
			
		||||
					action: () => {
 | 
			
		||||
						this.$root.apis.input({
 | 
			
		||||
						this.$input({
 | 
			
		||||
							title: this.$t('enter-hashtag-tl-title')
 | 
			
		||||
						}).then(title => {
 | 
			
		||||
							this.$store.dispatch('settings/addDeckColumn', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -81,7 +81,7 @@ export default Vue.extend({
 | 
			
		|||
		onBannerClick() {
 | 
			
		||||
			if (!this.$store.getters.isSignedIn || this.$store.state.i.id != this.user.id) return;
 | 
			
		||||
 | 
			
		||||
			this.$root.apis.updateBanner().then(i => {
 | 
			
		||||
			this.$updateBanner().then(i => {
 | 
			
		||||
				this.user.bannerUrl = i.bannerUrl;
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -101,7 +101,7 @@ export default Vue.extend({
 | 
			
		|||
					listId: list.id,
 | 
			
		||||
					userId: this.user.id
 | 
			
		||||
				});
 | 
			
		||||
				this.$root.apis.dialog({
 | 
			
		||||
				this.$dialog({
 | 
			
		||||
					title: 'Done!',
 | 
			
		||||
					text: this.$t('list-pushed').replace('{user}', this.user.name).replace('{list}', list.title)
 | 
			
		||||
				});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ import VueI18n from 'vue-i18n';
 | 
			
		|||
import VueHotkey from './common/hotkey';
 | 
			
		||||
import App from './app.vue';
 | 
			
		||||
import checkForUpdate from './common/scripts/check-for-update';
 | 
			
		||||
import MiOS, { API } from './mios';
 | 
			
		||||
import MiOS from './mios';
 | 
			
		||||
import { clientVersion as version, codename, lang } from './config';
 | 
			
		||||
import { builtinThemes, lightTheme, applyTheme } from './theme';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -180,16 +180,14 @@ if (localStorage.getItem('should-refresh') == 'true') {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// MiOSを初期化してコールバックする
 | 
			
		||||
export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API) => [Vue, MiOS]) => void, sw = false) => {
 | 
			
		||||
export default (callback: (launch: (router: VueRouter) => [Vue, MiOS]) => void, sw = false) => {
 | 
			
		||||
	const os = new MiOS(sw);
 | 
			
		||||
 | 
			
		||||
	os.init(() => {
 | 
			
		||||
		// アプリ基底要素マウント
 | 
			
		||||
		document.body.innerHTML = '<div id="app"></div>';
 | 
			
		||||
 | 
			
		||||
		const launch = (router: VueRouter, api?: (os: MiOS) => API) => {
 | 
			
		||||
			os.apis = api ? api(os) : null;
 | 
			
		||||
 | 
			
		||||
		const launch = (router: VueRouter) => {
 | 
			
		||||
			//#region theme
 | 
			
		||||
			os.store.watch(s => {
 | 
			
		||||
				return s.device.darkmode;
 | 
			
		||||
| 
						 | 
				
			
			@ -285,7 +283,6 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
 | 
			
		|||
							windows: os.windows
 | 
			
		||||
						},
 | 
			
		||||
						stream: os.stream,
 | 
			
		||||
						apis: os.apis,
 | 
			
		||||
						instanceName: os.instanceName
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
| 
						 | 
				
			
			@ -293,7 +290,14 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
 | 
			
		|||
					api: os.api,
 | 
			
		||||
					getMeta: os.getMeta,
 | 
			
		||||
					getMetaSync: os.getMetaSync,
 | 
			
		||||
					new: os.new,
 | 
			
		||||
					new(vm, props) {
 | 
			
		||||
						const x = new vm({
 | 
			
		||||
							parent: this,
 | 
			
		||||
							propsData: props
 | 
			
		||||
						}).$mount();
 | 
			
		||||
						document.body.appendChild(x.$el);
 | 
			
		||||
						return x;
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				router,
 | 
			
		||||
				render: createEl => createEl(App)
 | 
			
		||||
| 
						 | 
				
			
			@ -304,18 +308,18 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
 | 
			
		|||
			// マウント
 | 
			
		||||
			app.$mount('#app');
 | 
			
		||||
 | 
			
		||||
			return [app, os] as [Vue, MiOS];
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		callback(launch);
 | 
			
		||||
 | 
			
		||||
			//#region 更新チェック
 | 
			
		||||
			const preventUpdate = os.store.state.device.preventUpdate;
 | 
			
		||||
			if (!preventUpdate) {
 | 
			
		||||
				setTimeout(() => {
 | 
			
		||||
				checkForUpdate(os);
 | 
			
		||||
					checkForUpdate(app);
 | 
			
		||||
				}, 3000);
 | 
			
		||||
			}
 | 
			
		||||
			//#endregion
 | 
			
		||||
 | 
			
		||||
			return [app, os] as [Vue, MiOS];
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		callback(launch);
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,41 +15,6 @@ let spinner = null;
 | 
			
		|||
let pending = 0;
 | 
			
		||||
//#endregion
 | 
			
		||||
 | 
			
		||||
export type API = {
 | 
			
		||||
	chooseDriveFile: (opts: {
 | 
			
		||||
		title?: string;
 | 
			
		||||
		currentFolder?: any;
 | 
			
		||||
		multiple?: boolean;
 | 
			
		||||
	}) => Promise<any>;
 | 
			
		||||
 | 
			
		||||
	chooseDriveFolder: (opts: {
 | 
			
		||||
		title?: string;
 | 
			
		||||
		currentFolder?: any;
 | 
			
		||||
	}) => Promise<any>;
 | 
			
		||||
 | 
			
		||||
	dialog: (opts: {
 | 
			
		||||
		title: string;
 | 
			
		||||
		text: string;
 | 
			
		||||
		actions?: Array<{
 | 
			
		||||
			text: string;
 | 
			
		||||
			id?: string;
 | 
			
		||||
		}>;
 | 
			
		||||
	}) => Promise<string>;
 | 
			
		||||
 | 
			
		||||
	input: (opts: {
 | 
			
		||||
		title: string;
 | 
			
		||||
		placeholder?: string;
 | 
			
		||||
		default?: string;
 | 
			
		||||
	}) => Promise<string>;
 | 
			
		||||
 | 
			
		||||
	post: (opts?: {
 | 
			
		||||
		reply?: any;
 | 
			
		||||
		renote?: any;
 | 
			
		||||
	}) => void;
 | 
			
		||||
 | 
			
		||||
	notify: (message: string) => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Misskey Operating System
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -70,16 +35,6 @@ export default class MiOS extends EventEmitter {
 | 
			
		|||
 | 
			
		||||
	public app: Vue;
 | 
			
		||||
 | 
			
		||||
	@autobind
 | 
			
		||||
	public new(vm, props) {
 | 
			
		||||
		const x = new vm({
 | 
			
		||||
			parent: this.app,
 | 
			
		||||
			propsData: props
 | 
			
		||||
		}).$mount();
 | 
			
		||||
		document.body.appendChild(x.$el);
 | 
			
		||||
		return x;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Whether is debug mode
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			@ -89,8 +44,6 @@ export default class MiOS extends EventEmitter {
 | 
			
		|||
 | 
			
		||||
	public store: ReturnType<typeof initStore>;
 | 
			
		||||
 | 
			
		||||
	public apis: API;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * A connection manager of home stream
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
import Chooser from '../views/components/drive-file-chooser.vue';
 | 
			
		||||
 | 
			
		||||
export default function(opts) {
 | 
			
		||||
	return new Promise((res, rej) => {
 | 
			
		||||
		const o = opts || {};
 | 
			
		||||
		const w = new Chooser({
 | 
			
		||||
			propsData: {
 | 
			
		||||
				title: o.title,
 | 
			
		||||
				multiple: o.multiple,
 | 
			
		||||
				initFolder: o.currentFolder
 | 
			
		||||
			}
 | 
			
		||||
		}).$mount();
 | 
			
		||||
		w.$once('selected', file => {
 | 
			
		||||
			res(file);
 | 
			
		||||
		});
 | 
			
		||||
		document.body.appendChild(w.$el);
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
import Chooser from '../views/components/drive-folder-chooser.vue';
 | 
			
		||||
 | 
			
		||||
export default function(opts) {
 | 
			
		||||
	return new Promise((res, rej) => {
 | 
			
		||||
		const o = opts || {};
 | 
			
		||||
		const w = new Chooser({
 | 
			
		||||
			propsData: {
 | 
			
		||||
				title: o.title,
 | 
			
		||||
				initFolder: o.currentFolder
 | 
			
		||||
			}
 | 
			
		||||
		}).$mount();
 | 
			
		||||
		w.$once('selected', folder => {
 | 
			
		||||
			res(folder);
 | 
			
		||||
		});
 | 
			
		||||
		document.body.appendChild(w.$el);
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
import OS from '../../mios';
 | 
			
		||||
import Dialog from '../views/components/dialog.vue';
 | 
			
		||||
 | 
			
		||||
export default (os: OS) => opts => {
 | 
			
		||||
	return new Promise<string>((res, rej) => {
 | 
			
		||||
		const o = opts || {};
 | 
			
		||||
		const d = os.new(Dialog, {
 | 
			
		||||
			title: o.title,
 | 
			
		||||
			text: o.text,
 | 
			
		||||
			modal: o.modal,
 | 
			
		||||
			buttons: o.actions
 | 
			
		||||
		});
 | 
			
		||||
		d.$once('clicked', id => {
 | 
			
		||||
			res(id);
 | 
			
		||||
		});
 | 
			
		||||
		document.body.appendChild(d.$el);
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +0,0 @@
 | 
			
		|||
export default function(opts) {
 | 
			
		||||
	return new Promise<string>((res, rej) => {
 | 
			
		||||
		const x = window.prompt(opts.title);
 | 
			
		||||
		if (x) {
 | 
			
		||||
			res(x);
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
export default function(message) {
 | 
			
		||||
	alert(message);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,24 +0,0 @@
 | 
			
		|||
import PostForm from '../views/components/post-form-dialog.vue';
 | 
			
		||||
 | 
			
		||||
export default (os) => (opts) => {
 | 
			
		||||
	const o = opts || {};
 | 
			
		||||
 | 
			
		||||
	document.documentElement.style.overflow = 'hidden';
 | 
			
		||||
 | 
			
		||||
	function recover() {
 | 
			
		||||
		document.documentElement.style.overflow = 'auto';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const vm = new PostForm({
 | 
			
		||||
		parent: os.app,
 | 
			
		||||
		propsData: {
 | 
			
		||||
			reply: o.reply,
 | 
			
		||||
			renote: o.renote
 | 
			
		||||
		}
 | 
			
		||||
	}).$mount();
 | 
			
		||||
	vm.$once('cancel', recover);
 | 
			
		||||
	vm.$once('posted', recover);
 | 
			
		||||
	if (o.cb) vm.$once('closed', o.cb);
 | 
			
		||||
	document.body.appendChild(vm.$el);
 | 
			
		||||
	(vm as any).focus();
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
 * Mobile Client
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
import VueRouter from 'vue-router';
 | 
			
		||||
 | 
			
		||||
// Style
 | 
			
		||||
| 
						 | 
				
			
			@ -9,13 +10,6 @@ import './style.styl';
 | 
			
		|||
 | 
			
		||||
import init from '../init';
 | 
			
		||||
 | 
			
		||||
import chooseDriveFolder from './api/choose-drive-folder';
 | 
			
		||||
import chooseDriveFile from './api/choose-drive-file';
 | 
			
		||||
import dialog from './api/dialog';
 | 
			
		||||
import input from './api/input';
 | 
			
		||||
import post from './api/post';
 | 
			
		||||
import notify from './api/notify';
 | 
			
		||||
 | 
			
		||||
import MkIndex from './views/pages/index.vue';
 | 
			
		||||
import MkSignup from './views/pages/signup.vue';
 | 
			
		||||
import MkUser from './views/pages/user.vue';
 | 
			
		||||
| 
						 | 
				
			
			@ -39,10 +33,94 @@ import MkTag from './views/pages/tag.vue';
 | 
			
		|||
import MkShare from './views/pages/share.vue';
 | 
			
		||||
import MkFollow from '../common/views/pages/follow.vue';
 | 
			
		||||
 | 
			
		||||
import PostForm from './views/components/post-form-dialog.vue';
 | 
			
		||||
import FileChooser from './views/components/drive-file-chooser.vue';
 | 
			
		||||
import FolderChooser from './views/components/drive-folder-chooser.vue';
 | 
			
		||||
import Dialog from './views/components/dialog.vue';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * init
 | 
			
		||||
 */
 | 
			
		||||
init((launch) => {
 | 
			
		||||
	Vue.mixin({
 | 
			
		||||
		methods: {
 | 
			
		||||
			$post(opts) {
 | 
			
		||||
				const o = opts || {};
 | 
			
		||||
 | 
			
		||||
				document.documentElement.style.overflow = 'hidden';
 | 
			
		||||
 | 
			
		||||
				function recover() {
 | 
			
		||||
					document.documentElement.style.overflow = 'auto';
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				const vm = this.$root.new(PostForm, {
 | 
			
		||||
					reply: o.reply,
 | 
			
		||||
					renote: o.renote
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				vm.$once('cancel', recover);
 | 
			
		||||
				vm.$once('posted', recover);
 | 
			
		||||
				if (o.cb) vm.$once('closed', o.cb);
 | 
			
		||||
				(vm as any).focus();
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$chooseDriveFile(opts) {
 | 
			
		||||
				return new Promise((res, rej) => {
 | 
			
		||||
					const o = opts || {};
 | 
			
		||||
					const vm = this.$root.new(FileChooser, {
 | 
			
		||||
						title: o.title,
 | 
			
		||||
						multiple: o.multiple,
 | 
			
		||||
						initFolder: o.currentFolder
 | 
			
		||||
					});
 | 
			
		||||
					vm.$once('selected', file => {
 | 
			
		||||
						res(file);
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$chooseDriveFolder(opts) {
 | 
			
		||||
				return new Promise((res, rej) => {
 | 
			
		||||
					const o = opts || {};
 | 
			
		||||
					const vm = this.$root.new(FolderChooser, {
 | 
			
		||||
						title: o.title,
 | 
			
		||||
						initFolder: o.currentFolder
 | 
			
		||||
					});
 | 
			
		||||
					vm.$once('selected', folder => {
 | 
			
		||||
						res(folder);
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$input(opts) {
 | 
			
		||||
				return new Promise<string>((res, rej) => {
 | 
			
		||||
					const x = window.prompt(opts.title);
 | 
			
		||||
					if (x) {
 | 
			
		||||
						res(x);
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$dialog(opts) {
 | 
			
		||||
				return new Promise<string>((res, rej) => {
 | 
			
		||||
					const o = opts || {};
 | 
			
		||||
					const d = this.$root.new(Dialog, {
 | 
			
		||||
						title: o.title,
 | 
			
		||||
						text: o.text,
 | 
			
		||||
						modal: o.modal,
 | 
			
		||||
						buttons: o.actions
 | 
			
		||||
					});
 | 
			
		||||
					d.$once('clicked', id => {
 | 
			
		||||
						res(id);
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			$notify(message) {
 | 
			
		||||
				alert(message);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	// Register directives
 | 
			
		||||
	require('./views/directives');
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -85,12 +163,5 @@ init((launch) => {
 | 
			
		|||
	});
 | 
			
		||||
 | 
			
		||||
	// Launch the app
 | 
			
		||||
	launch(router, os => ({
 | 
			
		||||
		chooseDriveFolder,
 | 
			
		||||
		chooseDriveFile,
 | 
			
		||||
		dialog: dialog(os),
 | 
			
		||||
		input,
 | 
			
		||||
		post: post(os),
 | 
			
		||||
		notify
 | 
			
		||||
	}));
 | 
			
		||||
	launch(router);
 | 
			
		||||
}, true);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -101,7 +101,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		move() {
 | 
			
		||||
			this.$root.apis.chooseDriveFolder().then(folder => {
 | 
			
		||||
			this.$chooseDriveFolder().then(folder => {
 | 
			
		||||
				this.$root.api('drive/files/update', {
 | 
			
		||||
					fileId: this.file.id,
 | 
			
		||||
					folderId: folder == null ? null : folder.id
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -439,7 +439,7 @@ export default Vue.extend({
 | 
			
		|||
				alert(this.$t('root-move-alert'));
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			this.$root.apis.chooseDriveFolder().then(folder => {
 | 
			
		||||
			this.$chooseDriveFolder().then(folder => {
 | 
			
		||||
				this.$root.api('drive/folders/update', {
 | 
			
		||||
					parentId: folder ? folder.id : null,
 | 
			
		||||
					folderId: this.folder.id
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -196,13 +196,13 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		reply() {
 | 
			
		||||
			this.$root.apis.post({
 | 
			
		||||
			this.$post({
 | 
			
		||||
				reply: this.p
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		renote() {
 | 
			
		||||
			this.$root.apis.post({
 | 
			
		||||
			this.$post({
 | 
			
		||||
				renote: this.p
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -220,7 +220,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		chooseFileFromDrive() {
 | 
			
		||||
			this.$root.apis.chooseDriveFile({
 | 
			
		||||
			this.$chooseDriveFile({
 | 
			
		||||
				multiple: true
 | 
			
		||||
			}).then(files => {
 | 
			
		||||
				files.forEach(this.attachMedia);
 | 
			
		||||
| 
						 | 
				
			
			@ -279,7 +279,7 @@ export default Vue.extend({
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		addVisibleUser() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('username-prompt')
 | 
			
		||||
			}).then(acct => {
 | 
			
		||||
				if (acct.startsWith('@')) acct = acct.substr(1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@
 | 
			
		|||
			<button class="nav" @click="$parent.isDrawerOpening = true"><fa icon="bars"/></button>
 | 
			
		||||
			<i v-if="hasUnreadNotification || hasUnreadMessagingMessage || hasGameInvitation" class="circle"><fa icon="circle"/></i>
 | 
			
		||||
			<h1>
 | 
			
		||||
				<slot>{{ os.instanceName }}</slot>
 | 
			
		||||
				<slot>{{ $root.instanceName }}</slot>
 | 
			
		||||
			</h1>
 | 
			
		||||
			<slot name="func"></slot>
 | 
			
		||||
		</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -139,7 +139,7 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
	methods: {
 | 
			
		||||
		fn() {
 | 
			
		||||
			this.$root.apis.post();
 | 
			
		||||
			this.$post();
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		saveSrc() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -339,16 +339,16 @@ export default Vue.extend({
 | 
			
		|||
 | 
			
		||||
		checkForUpdate() {
 | 
			
		||||
			this.checkingForUpdate = true;
 | 
			
		||||
			checkForUpdate((this as any).os, true, true).then(newer => {
 | 
			
		||||
			checkForUpdate(this.$root, true, true).then(newer => {
 | 
			
		||||
				this.checkingForUpdate = false;
 | 
			
		||||
				this.latestVersion = newer;
 | 
			
		||||
				if (newer == null) {
 | 
			
		||||
					this.$root.apis.dialog({
 | 
			
		||||
					this.$dialog({
 | 
			
		||||
						title: this.$t('no-updates'),
 | 
			
		||||
						text: this.$t('no-updates-desc')
 | 
			
		||||
					});
 | 
			
		||||
				} else {
 | 
			
		||||
					this.$root.apis.dialog({
 | 
			
		||||
					this.$dialog({
 | 
			
		||||
						title: this.$t('update-available'),
 | 
			
		||||
						text: this.$t('update-available-desc')
 | 
			
		||||
					});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ export default Vue.extend({
 | 
			
		|||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		fn() {
 | 
			
		||||
			this.$root.apis.input({
 | 
			
		||||
			this.$input({
 | 
			
		||||
				title: this.$t('enter-list-name'),
 | 
			
		||||
			}).then(async title => {
 | 
			
		||||
				const list = await this.$root.api('users/lists/create', {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue