1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-07-05 11:24:44 +02:00

Compare commits

...

9 Commits

Author SHA1 Message Date
syuilo
f968d05ea0 2.37.7 2018-06-12 09:10:52 +09:00
syuilo
d6e5dc2167 Fix bugs 2018-06-12 09:10:34 +09:00
syuilo
460147fea2 2.37.6 2018-06-12 08:59:36 +09:00
syuilo
cea44834bb Improve usability 2018-06-12 08:58:50 +09:00
syuilo
1af50fd7b8 冗長なハッシュタグの表示を無くした 2018-06-12 08:43:48 +09:00
syuilo
b18013025f 🎨 2018-06-12 08:09:27 +09:00
syuilo
399eb60809 2.37.5 2018-06-12 02:47:17 +09:00
syuilo
ed67e3506b ✌️ 2018-06-12 02:46:54 +09:00
syuilo
d8ff37fc45 ✌️ 2018-06-12 02:28:28 +09:00
6 changed files with 66 additions and 23 deletions

View File

@@ -258,6 +258,7 @@ common/views/widgets/posts-monitor.vue:
common/views/widgets/hashtags.vue:
title: "ハッシュタグ"
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/server.vue:
title: "サーバー情報"

View File

@@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "2.37.4",
"clientVersion": "1.0.6465",
"version": "2.37.7",
"clientVersion": "1.0.6474",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,

View File

@@ -40,6 +40,17 @@ export default Vue.component('mk-note-html', {
ast = this.ast;
}
if (ast.filter(x => x.type != 'hashtag').length == 0) {
return;
}
while (
ast[ast.length - 1].type == 'hashtag' ||
(ast[ast.length - 1].type == 'text' && ast[ast.length - 1].content == ' ') ||
(ast[ast.length - 1].type == 'text' && ast[ast.length - 1].content == '\n')) {
ast.pop();
}
// Parse ast to DOM
const els = flatten(ast.map(token => {
switch (token.type) {
@@ -92,7 +103,7 @@ export default Vue.component('mk-note-html', {
case 'hashtag':
return createElement('a', {
attrs: {
href: `${url}/search?q=${token.content}`,
href: `${url}/tags/${token.content}`,
target: '_blank'
}
}, token.content);

View File

@@ -5,6 +5,7 @@
<div class="mkw-hashtags--body" :data-mobile="platform == 'mobile'">
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<p class="empty" v-else-if="stats.length == 0">%fa:exclamation-circle%%i18n:@empty%</p>
<transition-group v-else tag="div" name="chart">
<div v-for="stat in stats" :key="stat.tag">
<div class="tag">
@@ -65,8 +66,9 @@ export default define({
root(isDark)
.mkw-hashtags--body
> .fetching
> .empty
margin 0
padding 12px 16px
padding 16px
text-align center
color #aaa
@@ -85,7 +87,7 @@ root(isDark)
> div
display flex
align-items center
padding 16px
padding 14px 16px
&:not(:last-child)
border-bottom solid 1px isDark ? #393f4f : #eee

View File

@@ -5,7 +5,7 @@
<div class="gqpwvtwtprsbmnssnbicggtwqhmylhnq">
<template v-if="edit">
<header>
<select v-model="widgetAdderSelected">
<select v-model="widgetAdderSelected" @change="addWidget">
<option value="profile">%i18n:common.widgets.profile%</option>
<option value="analog-clock">%i18n:common.widgets.analog-clock%</option>
<option value="calendar">%i18n:common.widgets.calendar%</option>
@@ -30,20 +30,15 @@
<option value="nav">%i18n:common.widgets.nav%</option>
<option value="tips">%i18n:common.widgets.tips%</option>
</select>
<button @click="addWidget">%i18n:@add%</button>
</header>
<x-draggable
:list="column.widgets"
:options="{ handle: '.handle', animation: 150 }"
:options="{ animation: 150 }"
@sort="onWidgetSort"
>
<div v-for="widget in column.widgets" class="customize-container" :key="widget.id">
<header>
<span class="handle">%fa:bars%</span>{{ widget.name }}<button class="remove" @click="removeWidget(widget)">%fa:times%</button>
</header>
<div @click="widgetFunc(widget.id)">
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="deck"/>
</div>
<div v-for="widget in column.widgets" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="widgetFunc(widget.id)">
<button class="remove" @click="removeWidget(widget)">%fa:times%</button>
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="deck"/>
</div>
</x-draggable>
</template>
@@ -142,6 +137,13 @@ export default Vue.extend({
root(isDark)
.gqpwvtwtprsbmnssnbicggtwqhmylhnq
> header
padding 16px
> *
width 100%
padding 4px
.widget, .customize-container
margin 8px
@@ -149,7 +151,21 @@ root(isDark)
margin-top 0
.customize-container
background #fff
cursor move
> *:not(.remove)
pointer-events none
> .remove
position absolute
z-index 1
top 8px
right 8px
width 32px
height 32px
color #fff
background rgba(#000, 0.7)
border-radius 4px
> header
color isDark ? #fff : #000

View File

@@ -10,6 +10,8 @@ const rangeB = 1000 * 60 * 120; // 2時間
const coefficient = 1.5; // 「n倍」の部分
const requiredUsers = 3; // 最低何人がそのタグを投稿している必要があるか
const max = 5;
/**
* Get trends of hashtags
*/
@@ -43,7 +45,7 @@ module.exports = () => new Promise(async (res, rej) => {
return res([]);
}
let tags = [];
const tags = [];
// カウント
data.map(x => x._id).forEach(x => {
@@ -59,10 +61,10 @@ module.exports = () => new Promise(async (res, rej) => {
});
// 最低要求投稿者数を下回るならカットする
tags = tags.filter(tag => tag.count >= requiredUsers);
const limitedTags = tags.filter(tag => tag.count >= requiredUsers);
//#region 2. 1で取得したそれぞれのタグについて、「直近a分間のユニーク投稿数が今からa分前今からb分前の間のユニーク投稿数のn倍以上」かどうかを判定する
const hotsPromises = tags.map(async tag => {
const hotsPromises = limitedTags.map(async tag => {
const passedCount = (await Note.distinct('userId', {
tags: tag.name,
createdAt: {
@@ -71,7 +73,7 @@ module.exports = () => new Promise(async (res, rej) => {
}
}) as any).length;
if (tag.count > (passedCount * coefficient)) {
if (tag.count >= (passedCount * coefficient)) {
return tag;
} else {
return null;
@@ -79,13 +81,24 @@ module.exports = () => new Promise(async (res, rej) => {
});
//#endregion
const hots = (await Promise.all(hotsPromises))
// タグを人気順に並べ替え
let hots = (await Promise.all(hotsPromises))
.filter(x => x != null)
.sort((a, b) => b.count - a.count)
.map(tag => tag.name)
.slice(0, 5);
.slice(0, max);
//#region 2で話題と判定されたタグそれぞれについて過去の投稿数グラフを取得す
//#region 3. もし上記の方法でのトレンド抽出の結果、求められているタグ数に達しなければ「ただ単に現在投稿数が多いハッシュタグ」に切り替え
if (hots.length < max) {
hots = hots.concat(tags
.filter(tag => hots.indexOf(tag.name) == -1)
.sort((a, b) => b.count - a.count)
.map(tag => tag.name)
.slice(0, max - hots.length));
}
//#endregion
//#region 2(または3)で話題と判定されたタグそれぞれについて過去の投稿数グラフを取得する
const countPromises: Array<Promise<any[]>> = [];
const range = 20;