增加音乐,摇一摇,服务等页面
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* 秒数转时长 1 → 00:01
|
||||
*/
|
||||
export function secondToDuration(second, fixed = 0) {
|
||||
var sec = (second % 60).toFixed(fixed);
|
||||
var min = Math.floor(second / 60);
|
||||
if (min.toString().length < 2) {
|
||||
min = '0' + min;
|
||||
}
|
||||
if (sec < 10) {
|
||||
sec = '0' + sec;
|
||||
}
|
||||
return min + ':' + sec
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个对象是否相等
|
||||
* @param {Object} o1
|
||||
* @param {Object} o2
|
||||
*/
|
||||
export function objEquals(o1,o2){
|
||||
if(o1 && o2){
|
||||
return o1.platform == o2.platform && o1.id == o2.id;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function isExist(list,obj){
|
||||
for (let itemIndex in list) {
|
||||
const item = list[itemIndex];
|
||||
if (objEquals(item,obj)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function findIndex(list,obj){
|
||||
for (let itemIndex in list) {
|
||||
const item = list[itemIndex];
|
||||
if (objEquals(item,obj)) {
|
||||
return parseInt(itemIndex);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
export function findObj(list,obj){
|
||||
const index = findIndex(list,obj);
|
||||
if(inde != -1){
|
||||
return list[index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isFind(list,obj){
|
||||
const index = findIndex(list,obj);
|
||||
if(index != -1){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function showToast(title,duration = 2000,icon="none",position="bottom"){
|
||||
uni.showToast({
|
||||
title,
|
||||
icon,
|
||||
duration,
|
||||
position
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 格式化歌词
|
||||
* @param {String} lrcStr 歌词文本
|
||||
* @param {String} mode 格式 object 对象模式,array 数组模式
|
||||
*/
|
||||
export function formatLrc(lrcStr,mode = 'object'){
|
||||
const reg = /\[\d*:\d*(\.|:)\d*]/g
|
||||
const timeReg = /\[(\d{2,})\:(\d{2})(?:\.(\d{1,3}))?\]/g; // eslint-disable-line no-useless-escape
|
||||
let timeResult = [];
|
||||
let index = 0;
|
||||
if(mode == 'object'){
|
||||
let lrcs = {};
|
||||
lrcStr.split("\n").forEach(item => {
|
||||
const timeRegAry = item.match(reg);
|
||||
if (timeRegAry) {
|
||||
const time = timeRegAry[0];
|
||||
const min = parseInt(time.match(/\[\d*/i).toString().slice(1))
|
||||
const sec = parseInt(time.match(/\:\d*/i).toString().slice(1))
|
||||
const second = min * 60 + sec
|
||||
const content = item.replace(timeRegAry, "")
|
||||
lrcs[second] = {
|
||||
time,
|
||||
content
|
||||
};
|
||||
}
|
||||
})
|
||||
return lrcs;
|
||||
}else{
|
||||
let lrcs = [];
|
||||
lrcStr.split("\n").forEach(item => {
|
||||
const timeRegAry = item.match(reg);
|
||||
if (timeRegAry) {
|
||||
const time = timeRegAry[0];
|
||||
const min = parseInt(time.match(/\[\d*/i).toString().slice(1))
|
||||
const sec = parseInt(time.match(/\:\d*/i).toString().slice(1))
|
||||
const second = min * 60 + sec
|
||||
const content = item.replace(timeRegAry, "")
|
||||
lrcs.push({
|
||||
second,
|
||||
time,
|
||||
content
|
||||
});
|
||||
}
|
||||
})
|
||||
return lrcs;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
const storage_constants = {
|
||||
searchHistory:'searchHistory',
|
||||
paramSongList:'paramSongList',
|
||||
mySongList:'mySongList',
|
||||
playList:'playList',
|
||||
playMode:'playMode',
|
||||
progress:'progress',
|
||||
playSeconds:'playSeconds',
|
||||
playDuration:'playDuration',
|
||||
playIndex:'playIndex',
|
||||
isFirstRun:'isFirstRun',
|
||||
recentlyPlayList:'recentlyPlayList'
|
||||
}
|
||||
|
||||
|
||||
function set(key, value) {
|
||||
try {
|
||||
uni.setStorageSync(key, value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function get(key) {
|
||||
try {
|
||||
return uni.getStorageSync(key);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getDefault(key, defaultVal) {
|
||||
try {
|
||||
let val = uni.getStorageSync(key);
|
||||
if(val || val == 0){
|
||||
return val;
|
||||
}else{
|
||||
val = defaultVal;
|
||||
return val;
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
function getObj(key) {
|
||||
try {
|
||||
const val = uni.getStorageSync(key);
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getObjDefault(key, defaultVal) {
|
||||
try {
|
||||
const val = uni.getStorageSync(key);
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
return defaultVal;
|
||||
} catch (e) {
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
function getArray(key) {
|
||||
try {
|
||||
const val = uni.getStorageSync(key);
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
return [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function getArrayDefault(key, defaultVal) {
|
||||
try {
|
||||
const val = uni.getStorageSync(key);
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
return defaultVal;
|
||||
} catch (e) {
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
function clearStorage(){
|
||||
uni.clearStorage();
|
||||
let item = {
|
||||
coverImg:"/static/mylike.png",
|
||||
name:`我喜欢的音乐`,
|
||||
id:"mylike",
|
||||
url:null,
|
||||
singer:"我喜欢的音乐",
|
||||
desc:null,
|
||||
platform:'local',
|
||||
album:null,
|
||||
list:[]
|
||||
}
|
||||
let allSongList = [];
|
||||
allSongList.push(item);
|
||||
set(storage_constants.mySongList,allSongList)
|
||||
}
|
||||
|
||||
function remove(key){
|
||||
uni.removeStorageSync(key);
|
||||
}
|
||||
|
||||
|
||||
const storage = {
|
||||
set,
|
||||
get,
|
||||
getDefault,
|
||||
getObj,
|
||||
getObjDefault,
|
||||
getArray,
|
||||
getArrayDefault,
|
||||
clearStorage,
|
||||
remove
|
||||
}
|
||||
|
||||
export {
|
||||
storage,
|
||||
storage_constants
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
export const playModeConfig = {
|
||||
list:{id:'list',icon:'play-list-foreach',name:'列表循环'},
|
||||
random:{id:'random',icon:'play-random',name:'随机播放'},
|
||||
single:{id:'single',icon:'play-one-foreach',name:'单曲循环'}
|
||||
}
|
||||
|
||||
|
||||
export const config = {
|
||||
playModel:playModeConfig
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
import Vue from 'vue'
|
||||
import Store from './store.js'
|
||||
import {
|
||||
playModeConfig
|
||||
} from './config.js';
|
||||
import {
|
||||
storage,
|
||||
storage_constants
|
||||
} from "./StorageUtil.js"
|
||||
import * as util from "./BaseUtil.js"
|
||||
export default {
|
||||
extends: Store,
|
||||
data() {},
|
||||
methods: {
|
||||
initMusic() {
|
||||
let audioPlayer = null;
|
||||
/* #ifdef H5 */
|
||||
audioPlayer = uni.createInnerAudioContext();
|
||||
/* #endif */
|
||||
/* #ifdef APP-PLUS */
|
||||
audioPlayer = uni.getBackgroundAudioManager();
|
||||
/* #endif */
|
||||
audioPlayer.autoplay = false;
|
||||
|
||||
audioPlayer.onTimeUpdate((e) => {
|
||||
this.setPlaySeconds(audioPlayer.currentTime);
|
||||
let progress = (audioPlayer.currentTime / audioPlayer.duration) * 100;
|
||||
if (progress) {
|
||||
this.setProgress(progress);
|
||||
}
|
||||
this.updateLrc(false);
|
||||
});
|
||||
|
||||
audioPlayer.onCanplay(() => {
|
||||
this.setMusicIsReady(true);
|
||||
})
|
||||
audioPlayer.onError(()=>{
|
||||
util.showToast('播放错误,即将播放下一首');
|
||||
this.next();
|
||||
})
|
||||
|
||||
audioPlayer.onEnded(() => {
|
||||
if (playModeConfig.single.id == this.playMode.id) {
|
||||
this.setMusic(this.playIndex, null, () => {
|
||||
this.play();
|
||||
this.setPlayState(true);
|
||||
});
|
||||
} else if (playModeConfig.random.id == this.playMode.id) {
|
||||
const index = parseInt((this.playList.length - 1) * Math.random())
|
||||
this.setMusic(index, null, () => {
|
||||
this.play();
|
||||
this.setPlayState(true);
|
||||
});
|
||||
} else {
|
||||
this.next();
|
||||
}
|
||||
})
|
||||
Vue.prototype.audioPlayer = audioPlayer;
|
||||
Vue.prototype.prev = this.prev;
|
||||
Vue.prototype.next = this.next;
|
||||
Vue.prototype.stop = this.stop;
|
||||
Vue.prototype.pause = this.pause;
|
||||
Vue.prototype.play = this.play;
|
||||
Vue.prototype.loadLrc = this.loadLrc;
|
||||
Vue.prototype.setMusic = this.setMusic;
|
||||
// Vue.prototype.getMusicPlayUrl = this.musicApi.getPlayUrl;
|
||||
// Vue.prototype.getLrc = this.musicApi.getLrc;
|
||||
// Vue.prototype.getMusicOtherInfo = this.musicApi.getMusicOtherInfo
|
||||
const playMode = storage.get(storage_constants.playMode);
|
||||
if (!playMode) {
|
||||
this.setPlayMode(playModeConfig.list);
|
||||
}
|
||||
const mySongList = storage.getArrayDefault(storage_constants.mySongList, []);
|
||||
/**
|
||||
* 初始化歌词
|
||||
*/
|
||||
if (this.playList && this.playIndex >= 0) {
|
||||
let music = this.playList[this.playIndex];
|
||||
if (music) {
|
||||
this.loadLrc(music, () => {
|
||||
this.updateLrc(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 设置音乐
|
||||
* @param {Object} index
|
||||
* @param {type} progress
|
||||
* @param {Object} call
|
||||
*/
|
||||
setMusic(index, progress, call) {
|
||||
if (this.playList && this.playList.length > 0) {
|
||||
if (index == null) {
|
||||
index = 0
|
||||
}
|
||||
// 停止播放
|
||||
this.audioPlayer.stop();
|
||||
// 更新播放状态
|
||||
this.setPlayState(false);
|
||||
if (progress) {
|
||||
// 重置进度条
|
||||
this.setProgress(progress.progress || 0)
|
||||
// 重置播放秒数
|
||||
this.setPlaySeconds(progress.playSeconds || 0)
|
||||
} else {
|
||||
// 重置进度条
|
||||
this.setProgress(0)
|
||||
// 重置播放秒数
|
||||
this.setPlaySeconds(0)
|
||||
}
|
||||
// 重置总秒数
|
||||
this.setTotalSeconds(0)
|
||||
|
||||
// 音乐状态为未准备
|
||||
this.setMusicIsReady(false)
|
||||
let music = this.playList[index];
|
||||
/* this.getMusicOtherInfo(music,(musicOtherInfo)=>{
|
||||
music = musicOtherInfo;
|
||||
|
||||
}) */
|
||||
|
||||
const oldPlayMusic = this.playList[this.playIndex];
|
||||
if (!util.objEquals(oldPlayMusic, music)) {
|
||||
// 重置歌词
|
||||
this.setLrcs([{
|
||||
time: '[00:00.00]',
|
||||
content: '歌词加载中'
|
||||
}]);
|
||||
this.setLrc({
|
||||
time: '[00:00.00]',
|
||||
content: '歌词加载中'
|
||||
})
|
||||
}
|
||||
this.setPlayIndex(index);
|
||||
// 加载歌词
|
||||
this.loadLrc(music);
|
||||
// 获取播放地址
|
||||
Vue.prototype.getMusicPlayUrl && Vue.prototype.getMusicPlayUrl(music).then(playUrl => {
|
||||
console.log(`播放地址:${playUrl}`)
|
||||
this.audioPlayer.src = playUrl;
|
||||
this.audioPlayer.title = music.name;
|
||||
this.audioPlayer.singer = music.singer;
|
||||
this.audioPlayer.coverImgUrl = music.coverImg;
|
||||
let timer = setInterval(() => {
|
||||
if (this.musicIsReady) {
|
||||
this.setTotalSeconds(this.audioPlayer.duration)
|
||||
if (this.playSeconds > 0) {
|
||||
this.audioPlayer.seek(this.playSeconds)
|
||||
}
|
||||
this.setMusicIsReady(false)
|
||||
clearInterval(timer);
|
||||
if (call) {
|
||||
call();
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
})
|
||||
}
|
||||
},
|
||||
getMusicOtherInfo(music, call) {
|
||||
if (music.loadOtherInfo) {
|
||||
Vue.prototype.getMusicOtherInfo && Vue.prototype.getMusicOtherInfo(music).then(musicResult => {
|
||||
call(musicResult)
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 加载歌词
|
||||
*/
|
||||
loadLrc(music, call) {
|
||||
Vue.prototype.getLrc && Vue.prototype.getLrc(music).then(lrcStr => {
|
||||
if (lrcStr) {
|
||||
this.setLrcStr(lrcStr)
|
||||
if (call) {
|
||||
call();
|
||||
}
|
||||
} else {
|
||||
this.setLrcStr('[00:00.00]无歌词')
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 更新当前歌词
|
||||
* @param {Object} isInit
|
||||
*/
|
||||
updateLrc(isInit) {
|
||||
if (this.lrcs) {
|
||||
const sec = parseInt(this.playSeconds);
|
||||
let index = sec + 1;
|
||||
let line = this.lrcs[index];
|
||||
if (line) {
|
||||
this.setLrc(line);
|
||||
} else {
|
||||
if (isInit) {
|
||||
for (var i = index; i >= 0; i--) {
|
||||
let initLine = this.lrcs[i];
|
||||
if (initLine) {
|
||||
this.setLrc(initLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
* 播放
|
||||
*/
|
||||
play() {
|
||||
this.audioPlayer.play();
|
||||
this.setPlayState(true);
|
||||
const music = this.playList[this.playIndex];
|
||||
this.pushRecentlyPlayList(music);
|
||||
},
|
||||
/**
|
||||
* 暂停
|
||||
*/
|
||||
pause() {
|
||||
this.audioPlayer.pause();
|
||||
this.setPlayState(false);
|
||||
},
|
||||
/**
|
||||
* 停止
|
||||
*/
|
||||
stop() {
|
||||
this.audioPlayer.stop();
|
||||
this.setPlayState(false);
|
||||
this.setProgress(0);
|
||||
this.setPlaySeconds(0)
|
||||
},
|
||||
/**
|
||||
* 下一曲
|
||||
*/
|
||||
next() {
|
||||
const length = this.playList.length;
|
||||
let index = -1;
|
||||
if (this.playIndex == length - 1) {
|
||||
index = 0;
|
||||
} else {
|
||||
index = this.playIndex + 1;
|
||||
}
|
||||
this.setMusic(index, null, () => {
|
||||
this.play();
|
||||
this.setPlayState(true);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 上一曲
|
||||
*/
|
||||
prev() {
|
||||
const length = this.playList.length;
|
||||
let index = this.playIndex;
|
||||
if (index == 0) {
|
||||
index = length - 1;
|
||||
} else {
|
||||
index = index - 1;
|
||||
}
|
||||
this.setMusic(index, null, () => {
|
||||
this.play();
|
||||
this.setPlayState(true);
|
||||
});
|
||||
},
|
||||
pushRecentlyPlayList(music){
|
||||
let recentlyPlayList = storage.getArrayDefault(storage_constants.recentlyPlayList, []);
|
||||
let index = util.findIndex(recentlyPlayList,music);
|
||||
if(index >= 0){
|
||||
recentlyPlayList.splice(index,1)
|
||||
}
|
||||
recentlyPlayList.splice(0,0,music)
|
||||
this.setRecentlyPlayList(recentlyPlayList);
|
||||
this.$forceUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/* #ifdef H5 */
|
||||
const bgAudioManager = uni.createInnerAudioContext();
|
||||
/* #endif */
|
||||
/* #ifdef APP-PLUS */
|
||||
const bgAudioManager = uni.getBackgroundAudioManager();
|
||||
/* #endif */
|
||||
bgAudioManager.autoplay = false;
|
||||
|
||||
|
||||
function initPlayer(that){
|
||||
if(that.currentPlaySong){
|
||||
that.$u.vuex("currentPlayer",{
|
||||
playState:false,
|
||||
progress:0,
|
||||
musicId:that.currentPlaySong.id,
|
||||
});
|
||||
bgAudioManager.title = that.currentPlaySong.songName;
|
||||
bgAudioManager.singer = that.currentPlaySong.artist;
|
||||
bgAudioManager.coverImgUrl = that.currentPlaySong.pic;
|
||||
bgAudioManager.src = that.currentPlaySong.playSrc;
|
||||
console.log("播放器初始化完成");
|
||||
bindOnControllerPlay(that);
|
||||
}
|
||||
}
|
||||
|
||||
function bindOnControllerPlay(that){
|
||||
let playState=that.currentPlayer.playState;
|
||||
console.log("that.currentPlayer.progress",that.currentPlayer.progress);
|
||||
if(playState){
|
||||
bgAudioManager.pause();
|
||||
}else{
|
||||
if(that.currentPlayer.canPlay==false){
|
||||
initPlayer(that);
|
||||
return;
|
||||
}else{
|
||||
bgAudioManager.play();
|
||||
that.$u.vuex("currentPlayer.canPlay",true);
|
||||
}
|
||||
}
|
||||
playState=!playState;
|
||||
console.log("当前播放状态===",playState);
|
||||
that.$u.vuex("currentPlayer.playState",playState);
|
||||
that.$u.vuex("currentPlayer.canPlay",true);
|
||||
bgAudioManager.onTimeUpdate((e) => {
|
||||
let progress = (bgAudioManager.currentTime / bgAudioManager.duration) * 100;
|
||||
if (progress) {
|
||||
that.$u.vuex("currentPlayer.progress",progress);
|
||||
}
|
||||
});
|
||||
bgAudioManager.onError(()=>{
|
||||
resetPlayer(that);
|
||||
});
|
||||
bgAudioManager.onEnded(() => {
|
||||
resetPlayer(that);
|
||||
});
|
||||
}
|
||||
|
||||
function resetPlayer(that,player){
|
||||
bgAudioManager.stop();
|
||||
that.$u.vuex("currentPlayer.playState",false);
|
||||
that.$u.vuex("currentPlayer.progress",0);
|
||||
that.$u.vuex("currentPlayer.canPlay",false);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
initPlayer,
|
||||
bindOnControllerPlay,
|
||||
resetPlayer,
|
||||
bgAudioManager
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import {
|
||||
mapState,
|
||||
mapMutations
|
||||
} from 'vuex'
|
||||
import * as util from './BaseUtil.js'
|
||||
export default {
|
||||
computed: {
|
||||
...mapState(['totalSeconds', 'totalDuration', 'playSeconds', 'playDuration', 'progress', 'playState',
|
||||
'playMode', 'musicIsReady', 'playList', 'playIndex', 'lrcStr', 'lrcs', 'lrc', 'recentlyPlayList'
|
||||
]),
|
||||
...mapState(['paramSongList', 'isFirstRun', 'showPlayBar'])
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setPlayIndex', 'setTotalSeconds', 'setPlaySeconds', 'setProgress', 'setPlayState',
|
||||
'setPlayMode', 'setMusicIsReady', 'setPlayList', 'setLrcStr', 'setLrcs', 'setLrc', 'setRecentlyPlayList'
|
||||
]),
|
||||
...mapMutations(['setParamSongList', 'setIsFirstRun', 'setShowPlayBar']),
|
||||
like(music) {
|
||||
this.songListService.like(music)
|
||||
this.$forceUpdate();
|
||||
},
|
||||
unLike(music) {
|
||||
this.songListService.unLike(music);
|
||||
this.$forceUpdate();
|
||||
},
|
||||
isLike(music) {
|
||||
return this.musicService.isLike(music);
|
||||
},
|
||||
controllerPlay(type) {
|
||||
if (type == 'play') {
|
||||
if (this.playState) {
|
||||
this.pause();
|
||||
} else {
|
||||
if (this.isFirstRun) {
|
||||
const progress = {
|
||||
progress: this.progress,
|
||||
playSeconds: this.playSeconds
|
||||
}
|
||||
this.setMusic(this.playIndex, progress, () => {
|
||||
this.play();
|
||||
})
|
||||
} else {
|
||||
this.play();
|
||||
}
|
||||
}
|
||||
} else if (type == 'next') {
|
||||
this.next();
|
||||
} else if (type == 'prev') {
|
||||
this.prev();
|
||||
}
|
||||
},
|
||||
playMusicByMusic(music) {
|
||||
let playList = this.playList;
|
||||
const index = util.findIndex(playList, music);
|
||||
let playIndex = null;
|
||||
if (index == -1) {
|
||||
playList.push(music);
|
||||
this.setPlayList(playList);
|
||||
playIndex = playList.length - 1;
|
||||
|
||||
} else {
|
||||
playIndex = index;
|
||||
}
|
||||
this.setMusic(playIndex, null, () => {
|
||||
this.play();
|
||||
})
|
||||
},
|
||||
nextPlay(music) {
|
||||
const playIndex = this.playIndex;
|
||||
let playList = this.playList;
|
||||
const musicIndex = util.findIndex(playList, music);
|
||||
if (musicIndex != -1) {
|
||||
if (playList.length - 1 == playIndex) {
|
||||
playList.push(music);
|
||||
} else {
|
||||
let index = playIndex + 1;
|
||||
playList[musicIndex] = playList.splice(index, 1, playList[musicIndex])[0];
|
||||
}
|
||||
|
||||
} else {
|
||||
const index = playIndex + 1;
|
||||
playList.splice(index, 0, music);
|
||||
}
|
||||
this.setPlayList(playList);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user