diff --git a/src/web/app/desktop/mixins.ls b/src/web/app/desktop/mixins.ls
index 9613bcc77..cb5680cce 100644
--- a/src/web/app/desktop/mixins.ls
+++ b/src/web/app/desktop/mixins.ls
@@ -29,10 +29,10 @@ module.exports = (me) ~>
 		input-dialog: require './scripts/input-dialog'
 
 	riot.mixin \update-avatar do
-		update-avatar: require './scripts/update-avatar.ls'
+		update-avatar: require './scripts/update-avatar'
 
 	riot.mixin \update-banner do
-		update-banner: require './scripts/update-banner.ls'
+		update-banner: require './scripts/update-banner'
 
 	riot.mixin \autocomplete do
 		Autocomplete: require './scripts/autocomplete'
diff --git a/src/web/app/desktop/scripts/update-avatar.js b/src/web/app/desktop/scripts/update-avatar.js
new file mode 100644
index 000000000..ad971f1b1
--- /dev/null
+++ b/src/web/app/desktop/scripts/update-avatar.js
@@ -0,0 +1,86 @@
+const riot = require('riot');
+const dialog = require('./dialog');
+const api = require('../../common/scripts/api');
+
+module.exports = (I, cb, file = null) => {
+	const fileSelected = file => {
+		const cropper = riot.mount(document.body.appendChild(document.createElement('mk-crop-window')), {
+			file: file,
+			title: 'アバターとして表示する部分を選択',
+			aspectRatio: 1 / 1
+		})[0];
+	
+		cropper.on('cropped', blob => {
+			const data = new FormData();
+			data.append('i', I.token);
+			data.append('file', blob, file.name + '.cropped.png');
+
+			api(I, 'drive/folders/find', {
+				name: 'アイコン'
+			}).then(iconFolder => {
+				if (iconFolder.length === 0) {
+					 api(I, 'drive/folders/create', {
+						name: 'アイコン'
+					}).then(iconFolder => {
+						uplaod(data, iconFolder);
+					});
+				} else {
+					uplaod(data, iconFolder[0]);
+				}
+			});
+		});
+	
+		cropper.on('skiped', () => {
+			set(file);
+		});
+	};
+
+	const uplaod = (data, folder) => {
+		const progress = riot.mount(document.body.appendChild(document.createElement('mk-progress-dialog')), {
+			title: '新しいアバターをアップロードしています'
+		})[0];
+	
+		if (folder) data.append('folder_id', folder.id);
+	
+		const xhr = new XMLHttpRequest();
+		xhr.open('POST', CONFIG.api.url + '/drive/files/create', true);
+		xhr.onload = e => {
+			const file = JSON.parse(e.target.response);
+			progress.close();
+			set(file);
+		};
+
+		xhr.upload.onprogress = e => {
+			if (e.lengthComputable) progress.updateProgress(e.loaded, e.total);
+		};
+
+		xhr.send(data);
+	};
+
+	const set = file => {
+		api(I, 'i/update', {
+			avatar_id: file.id
+		}).then(i => {
+			dialog('<i class="fa fa-info-circle"></i>アバターを更新しました',
+				'新しいアバターが反映されるまで時間がかかる場合があります。',
+			[{
+				text: 'わかった'
+			}]);
+
+			if (cb) cb(i);
+		});
+	};
+
+	if (file) {
+		fileSelected(file);
+	} else {
+		const browser = riot.mount(document.body.appendChild(document.createElement('mk-select-file-from-drive-window')), {
+			multiple: false,
+			title: '<i class="fa fa-picture-o"></i>アバターにする画像を選択'
+		})[0];
+
+		browser.one('selected', file => {
+			fileSelected(file);
+		});
+	}
+};
diff --git a/src/web/app/desktop/scripts/update-avatar.ls b/src/web/app/desktop/scripts/update-avatar.ls
deleted file mode 100644
index 351e54fe5..000000000
--- a/src/web/app/desktop/scripts/update-avatar.ls
+++ /dev/null
@@ -1,81 +0,0 @@
-# Update Avatar
-#================================
-
-riot = require 'riot'
-dialog = require './dialog.ls'
-api = require '../../common/scripts/api'
-
-module.exports = (I, cb, file = null) ~>
-
-	@file-selected = (file) ~>
-		cropper = document.body.append-child document.create-element \mk-crop-window
-		cropper = riot.mount cropper, do
-			file: file
-			title: 'アバターとして表示する部分を選択'
-			aspect-ratio: 1 / 1
-		.0
-		cropper.on \cropped (blob) ~>
-			data = new FormData!
-			data.append \i I.token
-			data.append \file blob, file.name + '.cropped.png'
-			api I, \drive/folders/find do
-				name: 'アイコン'
-			.then (icon-folder) ~>
-				if icon-folder.length == 0
-					api I, \drive/folders/create do
-						name: 'アイコン'
-					.then (icon-folder) ~>
-						@uplaod data, icon-folder
-				else
-					@uplaod data, icon-folder.0
-		cropper.on \skiped ~>
-			@set file
-
-	@uplaod = (data, folder) ~>
-
-		progress = document.body.append-child document.create-element \mk-progress-dialog
-		progress = riot.mount progress, do
-			title: '新しいアバターをアップロードしています'
-		.0
-
-		if folder?
-			data.append \folder_id folder.id
-
-		xhr = new XMLHttpRequest!
-		xhr.open \POST CONFIG.api.url + \/drive/files/create true
-		xhr.onload = (e) ~>
-			file = JSON.parse e.target.response
-			progress.close!
-			@set file
-
-		xhr.upload.onprogress = (e) ~>
-			if e.length-computable
-				progress.update-progress e.loaded, e.total
-
-		xhr.send data
-
-	@set = (file) ~>
-		api I, \i/update do
-			avatar_id: file.id
-		.then (i) ~>
-			dialog do
-				'<i class="fa fa-info-circle"></i>アバターを更新しました'
-				'新しいアバターが反映されるまで時間がかかる場合があります。'
-				[
-					text: \わかった
-				]
-			if cb? then cb i
-		.catch (err) ~>
-			console.error err
-			#@opts.ui.trigger \notification 'Error!'
-
-	if file?
-		@file-selected file
-	else
-		browser = document.body.append-child document.create-element \mk-select-file-from-drive-window
-		browser = riot.mount browser, do
-			multiple: false
-			title: '<i class="fa fa-picture-o"></i>アバターにする画像を選択'
-		.0
-		browser.one \selected (file) ~>
-			@file-selected file
diff --git a/src/web/app/desktop/scripts/update-banner.js b/src/web/app/desktop/scripts/update-banner.js
new file mode 100644
index 000000000..9242adcea
--- /dev/null
+++ b/src/web/app/desktop/scripts/update-banner.js
@@ -0,0 +1,86 @@
+const riot = require('riot');
+const dialog = require('./dialog');
+const api = require('../../common/scripts/api');
+
+module.exports = (I, cb, file = null) => {
+	const fileSelected = file => {
+		const cropper = riot.mount(document.body.appendChild(document.createElement('mk-crop-window')), {
+			file: file,
+			title: 'バナーとして表示する部分を選択',
+			aspectRatio: 16 / 9
+		})[0];
+	
+		cropper.on('cropped', blob => {
+			const data = new FormData();
+			data.append('i', I.token);
+			data.append('file', blob, file.name + '.cropped.png');
+
+			api(I, 'drive/folders/find', {
+				name: 'バナー'
+			}).then(iconFolder => {
+				if (iconFolder.length === 0) {
+					 api(I, 'drive/folders/create', {
+						name: 'バナー'
+					}).then(iconFolder => {
+						uplaod(data, iconFolder);
+					});
+				} else {
+					uplaod(data, iconFolder[0]);
+				}
+			});
+		});
+	
+		cropper.on('skiped', () => {
+			set(file);
+		});
+	};
+
+	const uplaod = (data, folder) => {
+		const progress = riot.mount(document.body.appendChild(document.createElement('mk-progress-dialog')), {
+			title: '新しいバナーをアップロードしています'
+		})[0];
+	
+		if (folder) data.append('folder_id', folder.id);
+	
+		const xhr = new XMLHttpRequest();
+		xhr.open('POST', CONFIG.api.url + '/drive/files/create', true);
+		xhr.onload = e => {
+			const file = JSON.parse(e.target.response);
+			progress.close();
+			set(file);
+		};
+
+		xhr.upload.onprogress = e => {
+			if (e.lengthComputable) progress.updateProgress(e.loaded, e.total);
+		};
+
+		xhr.send(data);
+	};
+
+	const set = file => {
+		api(I, 'i/update', {
+			banner_id: file.id
+		}).then(i => {
+			dialog('<i class="fa fa-info-circle"></i>バナーを更新しました',
+				'新しいバナーが反映されるまで時間がかかる場合があります。',
+			[{
+				text: 'わかりました。'
+			}]);
+
+			if (cb) cb(i);
+		});
+	};
+
+	if (file) {
+		fileSelected(file);
+	} else {
+		const browser = riot.mount(document.body.appendChild(document.createElement('mk-select-file-from-drive-window')), {
+			multiple: false,
+			title: '<i class="fa fa-picture-o"></i>バナーにする画像を選択'
+		})[0];
+
+		browser.one('selected', file => {
+			fileSelected(file);
+		});
+	}
+};
diff --git a/src/web/app/desktop/scripts/update-banner.ls b/src/web/app/desktop/scripts/update-banner.ls
deleted file mode 100644
index 2417b8ab2..000000000
--- a/src/web/app/desktop/scripts/update-banner.ls
+++ /dev/null
@@ -1,81 +0,0 @@
-# Update Banner
-#================================
-
-riot = require 'riot'
-dialog = require './dialog.ls'
-api = require '../../common/scripts/api'
-
-module.exports = (I, cb, file = null) ~>
-
-	@file-selected = (file) ~>
-		cropper = document.body.append-child document.create-element \mk-crop-window
-		cropper = riot.mount cropper, do
-			file: file
-			title: 'バナーとして表示する部分を選択'
-			aspect-ratio: 16 / 9
-		.0
-		cropper.on \cropped (blob) ~>
-			data = new FormData!
-			data.append \i I.token
-			data.append \file blob, file.name + '.cropped.png'
-			api I, \drive/folders/find do
-				name: 'バナー'
-			.then (banner-folder) ~>
-				if banner-folder.length == 0
-					api I, \drive/folders/create do
-						name: 'バナー'
-					.then (banner-folder) ~>
-						@uplaod data, banner-folder
-				else
-					@uplaod data, banner-folder.0
-		cropper.on \skiped ~>
-			@set file
-
-	@uplaod = (data, folder) ~>
-
-		progress = document.body.append-child document.create-element \mk-progress-dialog
-		progress = riot.mount progress, do
-			title: '新しいバナーをアップロードしています'
-		.0
-
-		if folder?
-			data.append \folder_id folder.id
-
-		xhr = new XMLHttpRequest!
-		xhr.open \POST CONFIG.api.url + \/drive/files/create true
-		xhr.onload = (e) ~>
-			file = JSON.parse e.target.response
-			progress.close!
-			@set file
-
-		xhr.upload.onprogress = (e) ~>
-			if e.length-computable
-				progress.update-progress e.loaded, e.total
-
-		xhr.send data
-
-	@set = (file) ~>
-		api I, \i/update do
-			banner_id: file.id
-		.then (i) ~>
-			dialog do
-				'<i class="fa fa-info-circle"></i>バナーを更新しました'
-				'新しいバナーが反映されるまで時間がかかる場合があります。'
-				[
-					text: \わかりました。
-				]
-			if cb? then cb i
-		.catch (err) ~>
-			console.error err
-			#@opts.ui.trigger \notification 'Error!'
-
-	if file?
-		@file-selected file
-	else
-		browser = document.body.append-child document.create-element \mk-select-file-from-drive-window
-		browser = riot.mount browser, do
-			multiple: false
-			title: '<i class="fa fa-picture-o"></i>バナーにする画像を選択'
-		.0
-		browser.one \selected (file) ~>
-			@file-selected file