mirror of
https://github.com/hotomoe/hotomoe
synced 2024-12-04 17:58:10 +09:00
wip
This commit is contained in:
parent
e8378c2bb8
commit
8fd6f24ee6
@ -108,41 +108,43 @@
|
|||||||
<script>
|
<script>
|
||||||
this.draw = () => {
|
this.draw = () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
nd = now.getDate()
|
const nd = now.getDate();
|
||||||
nm = now.getMonth()
|
const nm = now.getMonth();
|
||||||
ny = now.getFullYear()
|
const ny = now.getFullYear();
|
||||||
|
|
||||||
this.year = ny
|
this.year = ny;
|
||||||
this.month = nm + 1
|
this.month = nm + 1;
|
||||||
this.day = nd
|
this.day = nd;
|
||||||
this.week-day = [\日 '月' \火 '水' \木 '金' \土][now.get-day!]
|
this.weekDay = ['日', '月', '火', '水' '木', '金', '土'][now.getDay()];
|
||||||
|
|
||||||
@day-numer = (now - (new Date ny, nm, nd))
|
this.dayNumer = now - new Date(ny, nm, nd);
|
||||||
@day-denom = 1000ms * 60s * 60m * 24h
|
this.dayDenom = 1000/*ms*/ * 60/*s*/ * 60/*m*/ * 24/*h*/;
|
||||||
this.month-numer = (now - (new Date ny, nm, 1))
|
this.monthNumer = now - new Date(ny, nm, 1);
|
||||||
this.month-denom = (new Date ny, nm + 1, 1) - (new Date ny, nm, 1)
|
this.monthDenom = new Date(ny, nm + 1, 1) - new Date(ny, nm, 1);
|
||||||
@year-numer = (now - (new Date ny, 0, 1))
|
this.yearNumer = now - new Date(ny, 0, 1);
|
||||||
@year-denom = (new Date ny + 1, 0, 1) - (new Date ny, 0, 1)
|
this.yearDenom = new Date(ny + 1, 0, 1) - new Date(ny, 0, 1);
|
||||||
|
|
||||||
@day-p = @day-numer / @day-denom * 100
|
this.dayP = this.dayNumer / this.dayDenom * 100;
|
||||||
this.month-p = @month-numer / @month-denom * 100
|
this.monthP = this.monthNumer / this.monthDenom * 100;
|
||||||
@year-p = @year-numer / @year-denom * 100
|
this.yearP = this.yearNumer / this.yearDenom * 100;
|
||||||
|
|
||||||
this.is-holiday =
|
this.isHoliday = now.getDay() == 0 || now.getDay() == 6;
|
||||||
(now.get-day! == 0 or now.get-day! == 6)
|
|
||||||
|
|
||||||
this.special =
|
this.special =
|
||||||
| nm == 0 and nd == 1 => 'on-new-years-day'
|
nm == 0 && nd == 1 ? 'on-new-years-day' :
|
||||||
| _ => false
|
false;
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
|
};
|
||||||
|
|
||||||
@draw!
|
this.draw();
|
||||||
|
|
||||||
this.on('mount', () => {
|
this.on('mount', () => {
|
||||||
this.clock = setInterval @draw, 1000ms
|
this.clock = setInterval(this.draw, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
this.on('unmount', () => {
|
this.on('unmount', () => {
|
||||||
clearInterval @clock
|
clearInterval(this.clock);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</mk-calendar-home-widget>
|
</mk-calendar-home-widget>
|
||||||
|
@ -49,64 +49,70 @@
|
|||||||
this.mixin('i');
|
this.mixin('i');
|
||||||
this.mixin('api');
|
this.mixin('api');
|
||||||
|
|
||||||
this.is-loading = true
|
this.isLoading = true;
|
||||||
this.is-empty = false
|
this.isEmpty = false;
|
||||||
this.more-loading = false
|
this.moreLoading = false;
|
||||||
this.mode = 'all'
|
this.mode = 'all';
|
||||||
|
|
||||||
this.on('mount', () => {
|
this.on('mount', () => {
|
||||||
document.addEventListener 'keydown' this.on-document-keydown
|
document.addEventListener('keydown', this.onDocumentKeydown);
|
||||||
window.addEventListener 'scroll' this.on-scroll
|
window.addEventListener('scroll', this.onScroll);
|
||||||
|
|
||||||
@fetch =>
|
this.fetch(() => this.trigger('loaded'));
|
||||||
this.trigger('loaded');
|
});
|
||||||
|
|
||||||
this.on('unmount', () => {
|
this.on('unmount', () => {
|
||||||
document.removeEventListener 'keydown' this.on-document-keydown
|
document.removeEventListener('keydown', this.onDocumentKeydown);
|
||||||
window.removeEventListener 'scroll' this.on-scroll
|
window.removeEventListener('scroll', this.onScroll);
|
||||||
|
});
|
||||||
|
|
||||||
this.on-document-keydown = (e) => {
|
this.onDocumentKeydown = e => {
|
||||||
tag = e.target.tag-name.to-lower-case!
|
if (e.target.tagName != 'INPUT' && tag != 'TEXTAREA') {
|
||||||
if tag != 'input' and tag != 'textarea'
|
if (e.which == 84) { // t
|
||||||
if e.which == 84 // t
|
|
||||||
this.refs.timeline.focus();
|
this.refs.timeline.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.fetch = (cb) => {
|
this.fetch = cb => {
|
||||||
this.api('posts/mentions', {
|
this.api('posts/mentions', {
|
||||||
following: this.mode == 'following'
|
following: this.mode == 'following'
|
||||||
}).then((posts) => {
|
}).then(posts => {
|
||||||
this.is-loading = false
|
this.update({
|
||||||
this.is-empty = posts.length == 0
|
isLoading: false,
|
||||||
this.update();
|
isEmpty: posts.length == 0
|
||||||
this.refs.timeline.set-posts posts
|
});
|
||||||
if cb? then cb!
|
this.refs.timeline.setPosts(posts);
|
||||||
.catch (err) =>
|
if (cb) cb();
|
||||||
console.error err
|
});
|
||||||
if cb? then cb!
|
};
|
||||||
|
|
||||||
this.more = () => {
|
this.more = () => {
|
||||||
if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
|
if (this.moreLoading || this.isLoading || this.refs.timeline.posts.length == 0) return;
|
||||||
return
|
this.update({
|
||||||
this.more-loading = true
|
moreLoading: true
|
||||||
this.update();
|
});
|
||||||
this.api('posts/mentions', {
|
this.api('posts/mentions', {
|
||||||
following: this.mode == 'following'
|
following: this.mode == 'following',
|
||||||
max_id: this.refs.timeline.tail!.id
|
max_id: this.refs.timeline.tail().id
|
||||||
}).then((posts) => {
|
}).then(posts => {
|
||||||
this.more-loading = false
|
this.update({
|
||||||
this.update();
|
moreLoading: false
|
||||||
this.refs.timeline.prepend-posts posts
|
});
|
||||||
.catch (err) =>
|
this.refs.timeline.prependPosts(posts);
|
||||||
console.error err
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.on-scroll = () => {
|
this.onScroll = () => {
|
||||||
current = window.scrollY + window.inner-height
|
const current = window.scrollY + window.innerHeight;
|
||||||
if current > document.body.offset-height - 8
|
if (current > document.body.offsetHeight - 8) this.more();
|
||||||
@more!
|
};
|
||||||
|
|
||||||
this.set-mode = (mode) => {
|
this.setMode = mode => {
|
||||||
@update do
|
this.update({
|
||||||
mode: mode
|
mode: mode
|
||||||
@fetch!
|
});
|
||||||
|
this.fetch();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</mk-mentions-home-widget>
|
</mk-mentions-home-widget>
|
||||||
|
@ -13,9 +13,5 @@
|
|||||||
i
|
i
|
||||||
color #ccc
|
color #ccc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</mk-nav-home-widget>
|
</mk-nav-home-widget>
|
||||||
|
@ -44,7 +44,8 @@
|
|||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
this.settings = () => {
|
this.settings = () => {
|
||||||
w = riot.mount document.body.appendChild document.createElement 'mk-settings-window' .0
|
const w = riot.mount(document.body.appendChild(document.createElement('mk-settings-window')[0];
|
||||||
w.switch 'notification'
|
w.switch('notification');
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</mk-notifications-home-widget>
|
</mk-notifications-home-widget>
|
||||||
|
@ -60,28 +60,33 @@
|
|||||||
this.mixin('api');
|
this.mixin('api');
|
||||||
this.mixin('stream');
|
this.mixin('stream');
|
||||||
|
|
||||||
this.images = []
|
this.images = [];
|
||||||
this.initializing = true
|
this.initializing = true;
|
||||||
|
|
||||||
this.on('mount', () => {
|
this.on('mount', () => {
|
||||||
this.stream.on 'drive_file_created' this.onStreamDriveFileCreated
|
this.stream.on('drive_file_created', this.onStreamDriveFileCreated);
|
||||||
|
|
||||||
this.api('drive/stream', {
|
this.api('drive/stream', {
|
||||||
type: 'image/*'
|
type: 'image/*',
|
||||||
limit: 9images
|
limit: 9
|
||||||
}).then((images) => {
|
}).then(images => {
|
||||||
this.initializing = false
|
this.update({
|
||||||
this.images = images
|
initializing: false,
|
||||||
this.update();
|
images: images
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this.on('unmount', () => {
|
this.on('unmount', () => {
|
||||||
this.stream.off 'drive_file_created' this.onStreamDriveFileCreated
|
this.stream.off('drive_file_created', this.onStreamDriveFileCreated);
|
||||||
|
});
|
||||||
|
|
||||||
this.onStreamDriveFileCreated = (file) => {
|
this.onStreamDriveFileCreated = file => {
|
||||||
if /^image\/.+$/.test file.type
|
if (/^image\/.+$/.test(file.type)) {
|
||||||
@images.unshift file
|
this.images.unshift(file);
|
||||||
if @images.length > 9
|
if (this.images.length > 9) this.images.pop();
|
||||||
@images.pop!
|
|
||||||
this.update();
|
this.update();
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</mk-photo-stream-home-widget>
|
</mk-photo-stream-home-widget>
|
||||||
|
@ -46,10 +46,12 @@
|
|||||||
this.mixin('update-avatar');
|
this.mixin('update-avatar');
|
||||||
this.mixin('update-banner');
|
this.mixin('update-banner');
|
||||||
|
|
||||||
this.set-avatar = () => {
|
this.setAvatar = () => {
|
||||||
@update-avatar this.I
|
this.updateAvatar(this.I);
|
||||||
|
};
|
||||||
|
|
||||||
this.set-banner = () => {
|
this.setBanner = () => {
|
||||||
@update-banner this.I
|
this.updateBanner(this.I);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</mk-profile-home-widget>
|
</mk-profile-home-widget>
|
||||||
|
@ -67,28 +67,32 @@
|
|||||||
this.mixin('api');
|
this.mixin('api');
|
||||||
this.mixin('NotImplementedException');
|
this.mixin('NotImplementedException');
|
||||||
|
|
||||||
this.url = 'http://news.yahoo.co.jp/pickup/rss.xml'
|
this.url = 'http://news.yahoo.co.jp/pickup/rss.xml';
|
||||||
this.items = []
|
this.items = [];
|
||||||
this.initializing = true
|
this.initializing = true;
|
||||||
|
|
||||||
this.on('mount', () => {
|
this.on('mount', () => {
|
||||||
@fetch!
|
this.fetch();
|
||||||
this.clock = setInterval @fetch, 60000ms
|
this.clock = setInterval(this.fetch, 60000);
|
||||||
|
});
|
||||||
|
|
||||||
this.on('unmount', () => {
|
this.on('unmount', () => {
|
||||||
clearInterval @clock
|
clearInterval(this.clock);
|
||||||
|
});
|
||||||
|
|
||||||
this.fetch = () => {
|
this.fetch = () => {
|
||||||
this.api CONFIG.url + '/api:rss' do
|
this.api(CONFIG.url + '/api:rss', {
|
||||||
url: @url
|
url: this.url
|
||||||
}).then((feed) => {
|
}).then(feed => {
|
||||||
this.items = feed.rss.channel.item
|
this.update({
|
||||||
this.initializing = false
|
initializing: false,
|
||||||
this.update();
|
items: feed.rss.channel.item
|
||||||
.catch (err) ->
|
});
|
||||||
console.error err
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.settings = () => {
|
this.settings = () => {
|
||||||
@NotImplementedException!
|
this.NotImplementedException();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</mk-rss-reader-home-widget>
|
</mk-rss-reader-home-widget>
|
||||||
|
@ -36,76 +36,83 @@
|
|||||||
this.mixin('api');
|
this.mixin('api');
|
||||||
this.mixin('stream');
|
this.mixin('stream');
|
||||||
|
|
||||||
this.is-loading = true
|
this.isLoading = true;
|
||||||
this.is-empty = false
|
this.isEmpty = false;
|
||||||
this.more-loading = false
|
this.moreLoading = false;
|
||||||
this.no-following = this.I.following_count == 0
|
this.noFollowing = this.I.following_count == 0;
|
||||||
|
|
||||||
this.on('mount', () => {
|
this.on('mount', () => {
|
||||||
this.stream.on 'post' this.on-stream-post
|
this.stream.on('post', this.onStreamPost);
|
||||||
this.stream.on 'follow' this.on-stream-follow
|
this.stream.on('follow', this.onStreamFollow);
|
||||||
this.stream.on 'unfollow' this.on-stream-unfollow
|
this.stream.on('unfollow', this.onStreamUnfollow);
|
||||||
|
|
||||||
document.addEventListener 'keydown' this.on-document-keydown
|
document.addEventListener('keydown', this.onDocumentKeydown);
|
||||||
window.addEventListener 'scroll' this.on-scroll
|
window.addEventListener('scroll', this.onScroll);
|
||||||
|
|
||||||
@load =>
|
this.load(() => this.trigger('loaded'));
|
||||||
this.trigger('loaded');
|
});
|
||||||
|
|
||||||
this.on('unmount', () => {
|
this.on('unmount', () => {
|
||||||
this.stream.off 'post' this.on-stream-post
|
this.stream.off('post', this.onStreamPost);
|
||||||
this.stream.off 'follow' this.on-stream-follow
|
this.stream.off('follow', this.onStreamFollow);
|
||||||
this.stream.off 'unfollow' this.on-stream-unfollow
|
this.stream.off('unfollow', this.onStreamUnfollow);
|
||||||
|
|
||||||
document.removeEventListener 'keydown' this.on-document-keydown
|
document.removeEventListener('keydown', this.onDocumentKeydown);
|
||||||
window.removeEventListener 'scroll' this.on-scroll
|
window.removeEventListener('scroll', this.onScroll);
|
||||||
|
});
|
||||||
|
|
||||||
this.on-document-keydown = (e) => {
|
this.onDocumentKeydown = e => {
|
||||||
tag = e.target.tag-name.to-lower-case!
|
if (e.target.tagName != 'INPUT' && tag != 'TEXTAREA') {
|
||||||
if tag != 'input' and tag != 'textarea'
|
if (e.which == 84) { // t
|
||||||
if e.which == 84 // t
|
|
||||||
this.refs.timeline.focus();
|
this.refs.timeline.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.load = (cb) => {
|
this.load = (cb) => {
|
||||||
this.api 'posts/timeline'
|
this.api('posts/timeline').then(posts => {
|
||||||
}).then((posts) => {
|
this.update({
|
||||||
this.is-loading = false
|
isLoading: false,
|
||||||
this.is-empty = posts.length == 0
|
isEmpty: posts.length == 0
|
||||||
this.update();
|
});
|
||||||
this.refs.timeline.set-posts posts
|
this.refs.timeline.setPosts(posts);
|
||||||
if cb? then cb!
|
if (cb) cb();
|
||||||
.catch (err) =>
|
});
|
||||||
console.error err
|
};
|
||||||
if cb? then cb!
|
|
||||||
|
|
||||||
this.more = () => {
|
this.more = () => {
|
||||||
if @more-loading or @is-loading or this.refs.timeline.posts.length == 0
|
if (this.moreLoading || this.isLoading || this.refs.timeline.posts.length == 0) return;
|
||||||
return
|
this.update({
|
||||||
this.more-loading = true
|
moreLoading: true
|
||||||
this.update();
|
});
|
||||||
this.api('posts/timeline', {
|
this.api('posts/timeline', {
|
||||||
max_id: this.refs.timeline.tail!.id
|
max_id: this.refs.timeline.tail().id
|
||||||
}).then((posts) => {
|
}).then(posts => {
|
||||||
this.more-loading = false
|
this.update({
|
||||||
this.update();
|
moreLoading: false
|
||||||
this.refs.timeline.prepend-posts posts
|
});
|
||||||
.catch (err) =>
|
this.refs.timeline.prependPosts(posts);
|
||||||
console.error err
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.on-stream-post = (post) => {
|
this.onStreamPost = post => {
|
||||||
this.is-empty = false
|
this.update({
|
||||||
this.update();
|
isEmpty: false
|
||||||
this.refs.timeline.add-post post
|
});
|
||||||
|
this.refs.timeline.addPost(post);
|
||||||
|
};
|
||||||
|
|
||||||
this.on-stream-follow = () => {
|
this.onStreamFollow = () => {
|
||||||
this.load();
|
this.load();
|
||||||
|
};
|
||||||
|
|
||||||
this.on-stream-unfollow = () => {
|
this.onStreamUnfollow = () => {
|
||||||
this.load();
|
this.load();
|
||||||
|
};
|
||||||
|
|
||||||
this.on-scroll = () => {
|
this.onScroll = () => {
|
||||||
current = window.scrollY + window.inner-height
|
const current = window.scrollY + window.innerHeight;
|
||||||
if current > document.body.offset-height - 8
|
if (current > document.body.offsetHeight - 8) this.more();
|
||||||
@more!
|
};
|
||||||
</script>
|
</script>
|
||||||
</mk-timeline-home-widget>
|
</mk-timeline-home-widget>
|
||||||
|
@ -30,42 +30,45 @@
|
|||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
this.tips = [
|
this.tips = [
|
||||||
'<kbd>t</kbd>でタイムラインにフォーカスできます'
|
'<kbd>t</kbd>でタイムラインにフォーカスできます',
|
||||||
'<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます'
|
'<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます',
|
||||||
'投稿フォームにはファイルをドラッグ&ドロップできます'
|
'投稿フォームにはファイルをドラッグ&ドロップできます',
|
||||||
'投稿フォームにクリップボードにある画像データをペーストできます'
|
'投稿フォームにクリップボードにある画像データをペーストできます',
|
||||||
'ドライブにファイルをドラッグ&ドロップしてアップロードできます'
|
'ドライブにファイルをドラッグ&ドロップしてアップロードできます',
|
||||||
'ドライブでファイルをドラッグしてフォルダ移動できます'
|
'ドライブでファイルをドラッグしてフォルダ移動できます',
|
||||||
'ドライブでフォルダをドラッグしてフォルダ移動できます'
|
'ドライブでフォルダをドラッグしてフォルダ移動できます',
|
||||||
'ホームをカスタマイズできます(準備中)'
|
'ホームをカスタマイズできます(準備中)',
|
||||||
'MisskeyはMIT Licenseです'
|
'MisskeyはMIT Licenseです'
|
||||||
]
|
]
|
||||||
|
|
||||||
this.on('mount', () => {
|
this.on('mount', () => {
|
||||||
@set!
|
this.set();
|
||||||
this.clock = setInterval @change, 20000ms
|
this.clock = setInterval(this.change, 20000);
|
||||||
|
});
|
||||||
|
|
||||||
this.on('unmount', () => {
|
this.on('unmount', () => {
|
||||||
clearInterval @clock
|
clearInterval(this.clock);
|
||||||
|
});
|
||||||
|
|
||||||
this.set = () => {
|
this.set = () => {
|
||||||
this.refs.text.innerHTML = @tips[Math.floor Math.random! * @tips.length]
|
this.refs.text.innerHTML = this.tips[Math.floor(Math.random() * this.tips.length)];
|
||||||
this.update();
|
};
|
||||||
|
|
||||||
this.change = () => {
|
this.change = () => {
|
||||||
Velocity(this.refs.tip, {
|
Velocity(this.refs.tip, {
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}, {
|
}, {
|
||||||
duration: 500ms
|
duration: 500,
|
||||||
easing: 'linear'
|
easing: 'linear',
|
||||||
complete: @set
|
complete: this.set
|
||||||
}
|
});
|
||||||
|
|
||||||
Velocity(this.refs.tip, {
|
Velocity(this.refs.tip, {
|
||||||
opacity: 1
|
opacity: 1
|
||||||
}, {
|
}, {
|
||||||
duration: 500ms
|
duration: 500,
|
||||||
easing: 'linear'
|
easing: 'linear'
|
||||||
}
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</mk-tips-home-widget>
|
</mk-tips-home-widget>
|
||||||
|
@ -112,41 +112,39 @@
|
|||||||
this.mixin('api');
|
this.mixin('api');
|
||||||
this.mixin('user-preview');
|
this.mixin('user-preview');
|
||||||
|
|
||||||
this.users = null
|
this.users = null;
|
||||||
this.loading = true
|
this.loading = true;
|
||||||
|
|
||||||
this.limit = 3users
|
this.limit = 3;
|
||||||
this.page = 0
|
this.page = 0;
|
||||||
|
|
||||||
this.on('mount', () => {
|
this.on('mount', () => {
|
||||||
@fetch!
|
this.fetch();
|
||||||
this.clock = setInterval =>
|
});
|
||||||
if this.users.length < @limit
|
|
||||||
@fetch true
|
|
||||||
, 60000ms
|
|
||||||
|
|
||||||
this.on('unmount', () => {
|
this.fetch = () => {
|
||||||
clearInterval @clock
|
this.update({
|
||||||
|
loading: true,
|
||||||
this.fetch = (quiet = false) => {
|
users: null
|
||||||
this.loading = true
|
});
|
||||||
this.users = null
|
|
||||||
if not quiet then this.update();
|
|
||||||
this.api('users/recommendation', {
|
this.api('users/recommendation', {
|
||||||
limit: @limit
|
limit: this.limit,
|
||||||
offset: @limit * this.page
|
offset: this.limit * this.page
|
||||||
}).then((users) => {
|
}).then(users => {
|
||||||
this.loading = false
|
this.update({
|
||||||
this.users = users
|
loading: false,
|
||||||
this.update();
|
users: users
|
||||||
.catch (err, text-status) ->
|
});
|
||||||
console.error err
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.refresh = () => {
|
this.refresh = () => {
|
||||||
if this.users.length < @limit
|
if (this.users.length < this.limit) {
|
||||||
this.page = 0
|
this.page = 0;
|
||||||
else
|
} else {
|
||||||
this.page++
|
this.page++;
|
||||||
@fetch!
|
}
|
||||||
|
this.fetch();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</mk-user-recommendation-home-widget>
|
</mk-user-recommendation-home-widget>
|
||||||
|
Loading…
Reference in New Issue
Block a user