mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Add search box for history
This commit is contained in:
parent
9ceb91a42e
commit
2d32b79200
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -32,7 +32,7 @@
|
|||||||
"compact-layout.min.js": "B20609A7CBBDB1845FA0156FB5BE6B1E1A1B8B069EA85F65D16241DD2C12D738",
|
"compact-layout.min.js": "B20609A7CBBDB1845FA0156FB5BE6B1E1A1B8B069EA85F65D16241DD2C12D738",
|
||||||
"custom-control-background.min.css": "1981FD2BF3B17ECF33F98D5DEDAF0D32ACBE9532A51FDB70822286991AB98EF3",
|
"custom-control-background.min.css": "1981FD2BF3B17ECF33F98D5DEDAF0D32ACBE9532A51FDB70822286991AB98EF3",
|
||||||
"custom-control-background.min.js": "2A439B045A51D24F5115DD25995ED37E3D0371A074199FE6C727F2235F39C4D9",
|
"custom-control-background.min.js": "2A439B045A51D24F5115DD25995ED37E3D0371A074199FE6C727F2235F39C4D9",
|
||||||
"custom-navbar.min.css": "774F1BF8DE8FC5526468571909B3FD2875404721BC44C6346EC60807485833C4",
|
"custom-navbar.min.css": "6EADE807DC6AC0457599076FF67F126FBC9214F33EB0F78A66EB892545D33BA8",
|
||||||
"custom-navbar.min.html": "FA6ACF1CA1DB6D3BD2BE310646B89B028756A36BF434BEBABE2BF00789581A09",
|
"custom-navbar.min.html": "FA6ACF1CA1DB6D3BD2BE310646B89B028756A36BF434BEBABE2BF00789581A09",
|
||||||
"custom-navbar.min.js": "1D1BBBD9482EAFAF1F12DBAD7FC3E34FFE36CA55AC42839ACBB34FA4142C3646",
|
"custom-navbar.min.js": "1D1BBBD9482EAFAF1F12DBAD7FC3E34FFE36CA55AC42839ACBB34FA4142C3646",
|
||||||
"custom-navbar-activities.min.js": "7AC74BBC42C4AEB3DF50A169AF46F03998BF5E74722D78BFEF885F00B1AB003A",
|
"custom-navbar-activities.min.js": "7AC74BBC42C4AEB3DF50A169AF46F03998BF5E74722D78BFEF885F00B1AB003A",
|
||||||
@ -40,7 +40,7 @@
|
|||||||
"custom-navbar-category.min.js": "A8A6190C090C92525EBA0A3C0C70EFC37AC7D1AFEEAB2834F1D69934C1B1F4D1",
|
"custom-navbar-category.min.js": "A8A6190C090C92525EBA0A3C0C70EFC37AC7D1AFEEAB2834F1D69934C1B1F4D1",
|
||||||
"custom-navbar-component.min.js": "5CA104E636521F21BBD05D23E17BDDF945566DDA3042710D4D7E1DDD1677E30B",
|
"custom-navbar-component.min.js": "5CA104E636521F21BBD05D23E17BDDF945566DDA3042710D4D7E1DDD1677E30B",
|
||||||
"custom-navbar-favorites-list.min.js": "71931EEBCF0BA3B33D8E72FF56BD92F2A089907F7E54E863D1EDDE0EAA9242FE",
|
"custom-navbar-favorites-list.min.js": "71931EEBCF0BA3B33D8E72FF56BD92F2A089907F7E54E863D1EDDE0EAA9242FE",
|
||||||
"custom-navbar-history-list.min.js": "117EA03267C36C7DFCA17FE3270851135AA1FB8E49C9D2E875C3783B710B9BD6",
|
"custom-navbar-history-list.min.js": "08B3AE7CF9351E801BD644A92E6719C0A370336C3CC152DD2D6EBE7B6B55464C",
|
||||||
"custom-navbar-iframe.min.js": "DBE5844C2AA36057DBD33BBC5724D7D7F881AB15EC45A80228961942CD810A32",
|
"custom-navbar-iframe.min.js": "DBE5844C2AA36057DBD33BBC5724D7D7F881AB15EC45A80228961942CD810A32",
|
||||||
"custom-navbar-logo.min.js": "236CCC887A3917A6D4840889B7380B648197765B8CDA27CB233F3F1E3215F7BB",
|
"custom-navbar-logo.min.js": "236CCC887A3917A6D4840889B7380B648197765B8CDA27CB233F3F1E3215F7BB",
|
||||||
"custom-navbar-messages.min.js": "D7B315A4D8FD9E2EF9C1E40C1F3CA7EC18C5A87AC7A9410049061A0D851868DE",
|
"custom-navbar-messages.min.js": "D7B315A4D8FD9E2EF9C1E40C1F3CA7EC18C5A87AC7A9410049061A0D851868DE",
|
||||||
@ -54,12 +54,10 @@
|
|||||||
"custom-navbar-watchlater-list.min.js": "5503A751DD2FDC19A6F138201B8C1654916F2D9B467E6D8B845635A920BBC595",
|
"custom-navbar-watchlater-list.min.js": "5503A751DD2FDC19A6F138201B8C1654916F2D9B467E6D8B845635A920BBC595",
|
||||||
"danmaku-converter.min.js": "908389A7D4E5F8546075B74F41BF03BD974073B4203723A575CF22082B358692",
|
"danmaku-converter.min.js": "908389A7D4E5F8546075B74F41BF03BD974073B4203723A575CF22082B358692",
|
||||||
"dark.min.css": "86D2B120F4C46847F420F940673F184571EFDCA7079ECD9A1D791637E9F8A687",
|
"dark.min.css": "86D2B120F4C46847F420F940673F184571EFDCA7079ECD9A1D791637E9F8A687",
|
||||||
"dark.user.css": "5DCDC91167D39CFD04948447A99B72BD55A7A603ADE3AA48B45F316756717A3F",
|
"dark.user.css": "B87F6CD0331497D8FB88199C9CCFD68358036F1A7B59CA1223A9DF4A10342D2A",
|
||||||
"dark-important.min.css": "9381B563726BCA701DD77C7AD572793538A45CB839F56008A55EE46821EA1B05",
|
"dark-important.min.css": "9381B563726BCA701DD77C7AD572793538A45CB839F56008A55EE46821EA1B05",
|
||||||
"dark-navbar.min.css": "A2D91F11127D165571ACCC53004EDDB118CEE110F9B020D7E0541E1C8FAEA478",
|
"dark-navbar.min.css": "A2D91F11127D165571ACCC53004EDDB118CEE110F9B020D7E0541E1C8FAEA478",
|
||||||
"dark-schedule.min.js": "853C446547603F4F0425F19F09F73335C9EC451A790C1C07E5E5B88A09E9B453",
|
"dark-schedule.min.js": "853C446547603F4F0425F19F09F73335C9EC451A790C1C07E5E5B88A09E9B453",
|
||||||
"dark-slice-11.min.css": "CF1A2FF0B248F61DC5112B7E589A94F5A5E5BC576A36CF5766089D57D082E3A1",
|
|
||||||
"dark-slice-9.min.css": "64F4B626BD335BE08E3043431DEC58E5331C4832DBA56F1D14C74D9879C0CC7B",
|
|
||||||
"dark-styles.min.js": "BF0AAA18064DFE8378160EB6BE65B1EF706B20BC01141355265D2EB18A72EE55",
|
"dark-styles.min.js": "BF0AAA18064DFE8378160EB6BE65B1EF706B20BC01141355265D2EB18A72EE55",
|
||||||
"debounce.min.js": "54D33E1273C1F3FE19550BF1844339C3D54D6B01DF8A39C3162D95B93B079CFA",
|
"debounce.min.js": "54D33E1273C1F3FE19550BF1844339C3D54D6B01DF8A39C3162D95B93B079CFA",
|
||||||
"default-danmaku-settings.min.css": "D9942B184FEDA7B08CFA0C34920E97D7A83B81762DCBF757642EBB60F95FF25D",
|
"default-danmaku-settings.min.css": "D9942B184FEDA7B08CFA0C34920E97D7A83B81762DCBF757642EBB60F95FF25D",
|
||||||
|
|||||||
BIN
min/bundle.zip
BIN
min/bundle.zip
Binary file not shown.
2
min/custom-navbar-history-list.min.js
vendored
2
min/custom-navbar-history-list.min.js
vendored
File diff suppressed because one or more lines are too long
2
min/custom-navbar.min.css
vendored
2
min/custom-navbar.min.css
vendored
File diff suppressed because one or more lines are too long
@ -3,7 +3,7 @@
|
|||||||
@namespace Bilibili-Evolved
|
@namespace Bilibili-Evolved
|
||||||
@homepageURL https://github.com/the1812/Bilibili-Evolved
|
@homepageURL https://github.com/the1812/Bilibili-Evolved
|
||||||
@updateURL https://cdn.jsdelivr.net/gh/the1812/Bilibili-Evolved@preview/min/dark.user.css
|
@updateURL https://cdn.jsdelivr.net/gh/the1812/Bilibili-Evolved@preview/min/dark.user.css
|
||||||
@version 624.20
|
@version
|
||||||
@license MIT
|
@license MIT
|
||||||
@author Grant Howard (https://github.com/the1812), Coulomb-G (https://github.com/Coulomb-G)
|
@author Grant Howard (https://github.com/the1812), Coulomb-G (https://github.com/Coulomb-G)
|
||||||
==/UserStyle== */
|
==/UserStyle== */
|
||||||
|
|||||||
33
src/style/custom-navbar/_search-box.scss
Normal file
33
src/style/custom-navbar/_search-box.scss
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
@mixin search-box {
|
||||||
|
.search {
|
||||||
|
position: relative;
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-right: 16px;
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 4px;
|
||||||
|
border: none;
|
||||||
|
outline: none !important;
|
||||||
|
color: inherit;
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100%);
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
transition: 0.24s ease-out;
|
||||||
|
background-color: #8882;
|
||||||
|
}
|
||||||
|
&.not-empty,
|
||||||
|
&:focus-within {
|
||||||
|
&::after {
|
||||||
|
background-color: var(--theme-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
@import "../../common";
|
@import "../../common";
|
||||||
|
@import "../search-box";
|
||||||
@mixin tabs-animation {
|
@mixin tabs-animation {
|
||||||
&-enter-active,
|
&-enter-active,
|
||||||
&-leave-active {
|
&-leave-active {
|
||||||
@ -55,11 +56,12 @@
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
.header {
|
.header {
|
||||||
@include h-center();
|
@include h-center();
|
||||||
|
@include search-box();
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: 16px 12px;
|
margin: 16px 12px;
|
||||||
.tabs {
|
.tabs {
|
||||||
flex-grow: 1;
|
flex: 0;
|
||||||
margin-right: 48px;
|
margin-right: 16px;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
@include h-center();
|
@include h-center();
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
@ -101,6 +103,7 @@
|
|||||||
.more-info {
|
.more-info {
|
||||||
@include h-center();
|
@include h-center();
|
||||||
@include round-bar(26);
|
@include round-bar(26);
|
||||||
|
flex-shrink: 0;
|
||||||
padding: 4px 6px 4px 10px;
|
padding: 4px 6px 4px 10px;
|
||||||
background-color: #8882;
|
background-color: #8882;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@ -30,7 +30,7 @@ interface HistoryTab {
|
|||||||
type: string
|
type: string
|
||||||
api: string
|
api: string
|
||||||
moreLink: string
|
moreLink: string
|
||||||
getTimeline: (json: any) => Timeline
|
getItems: (json: any) => HistoryItem[]
|
||||||
}
|
}
|
||||||
const getTimeData = () => {
|
const getTimeData = () => {
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
@ -46,26 +46,38 @@ const getTimeData = () => {
|
|||||||
lastWeek,
|
lastWeek,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const simpleTimeGrouper = (historyItems: (HistoryItem & TimeData)[]) => {
|
const historyTimeGrouper = (historyItems: HistoryItem[]) => {
|
||||||
const { today, yesterday, lastWeek } = getTimeData()
|
if (historyItems.length === 0) {
|
||||||
const groups = _.groupBy(historyItems, h => {
|
return []
|
||||||
if (h.timestamp >= today) {
|
}
|
||||||
return '今天'
|
if ('timestamp' in historyItems[0]) {
|
||||||
}
|
const { today, yesterday, lastWeek } = getTimeData()
|
||||||
if (h.timestamp >= yesterday) {
|
const groups = _.groupBy(historyItems as (HistoryItem & TimeData)[], h => {
|
||||||
return '昨天'
|
if (h.timestamp >= today) {
|
||||||
}
|
return '今天'
|
||||||
if (h.timestamp >= lastWeek) {
|
}
|
||||||
return '本周'
|
if (h.timestamp >= yesterday) {
|
||||||
}
|
return '昨天'
|
||||||
return '更早'
|
}
|
||||||
})
|
if (h.timestamp >= lastWeek) {
|
||||||
return Object.entries(groups).map(([key, value]) => {
|
return '本周'
|
||||||
return {
|
}
|
||||||
name: key,
|
return '更早'
|
||||||
items: value,
|
})
|
||||||
}
|
return Object.entries(groups).map(([key, value]) => {
|
||||||
})
|
return {
|
||||||
|
name: key,
|
||||||
|
items: value,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: '最近观看',
|
||||||
|
items: historyItems
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const formatTime = (date: Date) => {
|
const formatTime = (date: Date) => {
|
||||||
const { yesterday } = getTimeData()
|
const { yesterday } = getTimeData()
|
||||||
@ -81,7 +93,7 @@ const tabs: HistoryTab[] = [
|
|||||||
type: 'video',
|
type: 'video',
|
||||||
api: 'https://api.bilibili.com/x/web-interface/history/cursor?type=archive&ps=30',
|
api: 'https://api.bilibili.com/x/web-interface/history/cursor?type=archive&ps=30',
|
||||||
moreLink: 'https://www.bilibili.com/account/history',
|
moreLink: 'https://www.bilibili.com/account/history',
|
||||||
getTimeline: json => {
|
getItems: json => {
|
||||||
const list: any[] = json.data.list
|
const list: any[] = json.data.list
|
||||||
const historyItems = list.map(item => {
|
const historyItems = list.map(item => {
|
||||||
const timestamp = item.view_at * 1000
|
const timestamp = item.view_at * 1000
|
||||||
@ -106,7 +118,7 @@ const tabs: HistoryTab[] = [
|
|||||||
historyItem.timeText = formatTime(historyItem.time)
|
historyItem.timeText = formatTime(historyItem.time)
|
||||||
return historyItem
|
return historyItem
|
||||||
})
|
})
|
||||||
return simpleTimeGrouper(historyItems)
|
return historyItems
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -114,7 +126,7 @@ const tabs: HistoryTab[] = [
|
|||||||
type: 'article',
|
type: 'article',
|
||||||
api: 'https://api.bilibili.com/x/web-interface/history/cursor?type=article&ps=30',
|
api: 'https://api.bilibili.com/x/web-interface/history/cursor?type=article&ps=30',
|
||||||
moreLink: '',
|
moreLink: '',
|
||||||
getTimeline: json => {
|
getItems: json => {
|
||||||
const list: any[] = json.data.list
|
const list: any[] = json.data.list
|
||||||
const historyItems = list.map(item => {
|
const historyItems = list.map(item => {
|
||||||
const timestamp = item.view_at * 1000
|
const timestamp = item.view_at * 1000
|
||||||
@ -132,7 +144,7 @@ const tabs: HistoryTab[] = [
|
|||||||
historyItem.timeText = formatTime(historyItem.time)
|
historyItem.timeText = formatTime(historyItem.time)
|
||||||
return historyItem
|
return historyItem
|
||||||
})
|
})
|
||||||
return simpleTimeGrouper(historyItems)
|
return historyItems
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -140,7 +152,7 @@ const tabs: HistoryTab[] = [
|
|||||||
type: 'live',
|
type: 'live',
|
||||||
api: 'https://api.live.bilibili.com/xlive/web-ucenter/v1/history/get_history_by_uid',
|
api: 'https://api.live.bilibili.com/xlive/web-ucenter/v1/history/get_history_by_uid',
|
||||||
moreLink: 'https://link.bilibili.com/p/center/index#/user-center/view-history/live',
|
moreLink: 'https://link.bilibili.com/p/center/index#/user-center/view-history/live',
|
||||||
getTimeline: json => {
|
getItems: json => {
|
||||||
const list: any[] = json.data.list
|
const list: any[] = json.data.list
|
||||||
const historyItems = list.map(item => {
|
const historyItems = list.map(item => {
|
||||||
return {
|
return {
|
||||||
@ -152,12 +164,7 @@ const tabs: HistoryTab[] = [
|
|||||||
title: item.title,
|
title: item.title,
|
||||||
} as HistoryItem
|
} as HistoryItem
|
||||||
})
|
})
|
||||||
return [
|
return historyItems
|
||||||
{
|
|
||||||
name: '最近观看',
|
|
||||||
items: historyItems
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -181,6 +188,9 @@ export class HistoryList extends NavbarComponent {
|
|||||||
<div class="tab-name">{{tab.name}}</div>
|
<div class="tab-name">{{tab.name}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="search">
|
||||||
|
<input type="text" placeholder="搜索" v-model="search">
|
||||||
|
</div>
|
||||||
<button class="more-info" :disabled="!selectedTab.moreLink || null" @click="viewMore()" title="查看更多">
|
<button class="more-info" :disabled="!selectedTab.moreLink || null" @click="viewMore()" title="查看更多">
|
||||||
查看更多
|
查看更多
|
||||||
<i class="mdi mdi-dots-horizontal"></i>
|
<i class="mdi mdi-dots-horizontal"></i>
|
||||||
@ -193,7 +203,7 @@ export class HistoryList extends NavbarComponent {
|
|||||||
<div class="loading-tip" v-if="timelineLoading" key="loading-tip">
|
<div class="loading-tip" v-if="timelineLoading" key="loading-tip">
|
||||||
加载中...
|
加载中...
|
||||||
</div>
|
</div>
|
||||||
<div class="time-group" v-for="t of timeline" :key="t.name">
|
<div class="time-group" v-for="t of filteredTimeline" :key="t.name">
|
||||||
<div class="time-group-name">{{t.name}}</div>
|
<div class="time-group-name">{{t.name}}</div>
|
||||||
<transition-group name="time-group" tag="div" class="time-group-items">
|
<transition-group name="time-group" tag="div" class="time-group-items">
|
||||||
<div class="time-group-item" v-for="h of t.items" :key="h.id">
|
<div class="time-group-item" v-for="h of t.items" :key="h.id">
|
||||||
@ -236,8 +246,24 @@ export class HistoryList extends NavbarComponent {
|
|||||||
data: {
|
data: {
|
||||||
tabs,
|
tabs,
|
||||||
selectedTab: tabs[0],
|
selectedTab: tabs[0],
|
||||||
|
/** 全部的历史项目 */
|
||||||
|
items: [],
|
||||||
|
/** 按时间段分组后的历史项目 */
|
||||||
timeline: [],
|
timeline: [],
|
||||||
timelineLoading: true,
|
timelineLoading: true,
|
||||||
|
search: '',
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
/** 按时间段分组, 关键词过滤后的历史项目 */
|
||||||
|
filteredTimeline(): Timeline {
|
||||||
|
if (!this.search) {
|
||||||
|
return this.timeline
|
||||||
|
}
|
||||||
|
const search: string = this.search.toLowerCase()
|
||||||
|
return historyTimeGrouper((this.items as HistoryItem[]).filter(it => {
|
||||||
|
return it.title.toLowerCase().includes(search) || it.upName.toLowerCase().includes(search)
|
||||||
|
}))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async updateTimeline() {
|
async updateTimeline() {
|
||||||
@ -249,8 +275,8 @@ export class HistoryList extends NavbarComponent {
|
|||||||
if (json.code !== 0) {
|
if (json.code !== 0) {
|
||||||
throw new Error(`加载历史记录失败: ${json.message}`)
|
throw new Error(`加载历史记录失败: ${json.message}`)
|
||||||
}
|
}
|
||||||
this.timeline = tab.getTimeline(json)
|
this.items = tab.getItems(json)
|
||||||
// console.log(_.cloneDeep(this.timeline))
|
this.timeline = historyTimeGrouper(this.items)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError(error)
|
logError(error)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
@import "../../common";
|
@import "../../common";
|
||||||
|
@import "../search-box";
|
||||||
.custom-navbar {
|
.custom-navbar {
|
||||||
@mixin button-background {
|
@mixin button-background {
|
||||||
background-color: #8882;
|
background-color: #8882;
|
||||||
@ -63,39 +64,9 @@
|
|||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
@include h-center();
|
@include h-center();
|
||||||
|
@include search-box();
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: 16px 12px;
|
margin: 16px 12px;
|
||||||
.search {
|
|
||||||
position: relative;
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-right: 16px;
|
|
||||||
input {
|
|
||||||
width: 100%;
|
|
||||||
padding: 4px;
|
|
||||||
border: none;
|
|
||||||
outline: none !important;
|
|
||||||
color: inherit;
|
|
||||||
background-color: transparent;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
&::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: calc(100%);
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 2px;
|
|
||||||
border-radius: 2px;
|
|
||||||
transition: 0.24s ease-out;
|
|
||||||
background-color: #8882;
|
|
||||||
}
|
|
||||||
&.not-empty,
|
|
||||||
&:focus-within {
|
|
||||||
&::after {
|
|
||||||
background-color: var(--theme-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.operations {
|
.operations {
|
||||||
@include h-center();
|
@include h-center();
|
||||||
.round-button {
|
.round-button {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user