mirror of
https://github.com/openmhz/trunk-server.git
synced 2026-11-12 08:47:40 -05:00
add contact and better initial call support
This commit is contained in:
@@ -7,7 +7,28 @@ var defaultNumResults = 50;
|
||||
|
||||
var channels = {};
|
||||
|
||||
async function get_calls(query, numResults, res) {
|
||||
const build_call_list = (items) => {
|
||||
let calls = [];
|
||||
for (var i=0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
call = {
|
||||
_id: item._id.toHexString(),
|
||||
talkgroupNum: item.talkgroupNum,
|
||||
url: item.url,
|
||||
filename: item.path + item.name,
|
||||
time: item.time,
|
||||
srcList: item.srcList,
|
||||
star: item.star,
|
||||
freq: item.freq,
|
||||
len: Math.round(item.len)
|
||||
};
|
||||
calls.push(call);
|
||||
}
|
||||
console.log("Finished Items is: " + items.length + " long and Calls is: " + calls.length)
|
||||
return calls;
|
||||
}
|
||||
|
||||
async function get_calls(query, numResults, middleDate, res) {
|
||||
|
||||
var calls = [];
|
||||
var fields = {
|
||||
@@ -25,23 +46,26 @@ async function get_calls(query, numResults, res) {
|
||||
|
||||
const sort = { length: -1 };
|
||||
try {
|
||||
console.log(query.filter);
|
||||
const items = await Call.find(query.filter, fields).sort(query.sort_order).limit(numResults);
|
||||
for (var i=0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
call = {
|
||||
_id: item._id.toHexString(),
|
||||
talkgroupNum: item.talkgroupNum,
|
||||
url: item.url,
|
||||
filename: item.path + item.name,
|
||||
time: item.time,
|
||||
srcList: item.srcList,
|
||||
star: item.star,
|
||||
freq: item.freq,
|
||||
len: Math.round(item.len)
|
||||
};
|
||||
calls.push(call);
|
||||
}
|
||||
const refined_items = build_call_list(items);
|
||||
//calls.concat(refined_items);
|
||||
calls.push(...refined_items);
|
||||
console.log(calls);
|
||||
|
||||
// if we are loading a list of calls around a specific Call ID, we want to load call before and after that call, so we call it twice.
|
||||
if (middleDate) {
|
||||
query.filter.time = {
|
||||
$gt: middleDate
|
||||
};
|
||||
console.log("doing a second query");
|
||||
console.log(query.filter);
|
||||
const items = await Call.find(query.filter, fields).sort(query.sort_order).limit(numResults);
|
||||
const refined_items = build_call_list(items);
|
||||
calls.push(...refined_items);
|
||||
console.log(calls);
|
||||
//calls.concat(refined_items);
|
||||
}
|
||||
res.json({
|
||||
calls: calls,
|
||||
direction: query.direction
|
||||
@@ -116,9 +140,6 @@ async function build_filter(filter_type, code, start_time, direction, shortName,
|
||||
filter.talkgroupNum = {
|
||||
$in: group.talkgroups
|
||||
};
|
||||
query['filter'] = filter;
|
||||
|
||||
get_calls(query, numResults, res);
|
||||
|
||||
} else {
|
||||
if ((filter_type == "talkgroup") || (filter_type == "group")) {
|
||||
@@ -132,14 +153,18 @@ async function build_filter(filter_type, code, start_time, direction, shortName,
|
||||
}
|
||||
}
|
||||
|
||||
query['filter'] = filter;
|
||||
|
||||
get_calls(query, numResults, res);
|
||||
}
|
||||
} else {
|
||||
query['filter'] = filter;
|
||||
get_calls(query, numResults, res);
|
||||
}
|
||||
}
|
||||
|
||||
if (direction=="middle") {
|
||||
query['filter'] = filter;
|
||||
get_calls(query, numResults, start, res);
|
||||
} else {
|
||||
query['filter'] = filter;
|
||||
get_calls(query, numResults, false, res);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -302,6 +327,19 @@ exports.get_call = async function (req, res) {
|
||||
|
||||
}
|
||||
|
||||
// This is what you use when you want to get some calls before and after a timestamp.
|
||||
|
||||
exports.get_date_calls = function (req, res) {
|
||||
var filter_code = req.query["filter-code"];
|
||||
var filter_type = req.query["filter-type"];
|
||||
var starred = req.query["filter-starred"] === 'true' ? true : false;
|
||||
var start_time = parseInt(req.query["time"]);
|
||||
var short_name = req.params.shortName.toLowerCase();
|
||||
//console.log("[" + short_name + "] Next Calls - time: " + start_time + " Filter code: " + filter_code + " Filter Type: " + filter_type);
|
||||
|
||||
build_filter(filter_type, filter_code, start_time, 'middle', short_name, defaultNumResults, starred, res);
|
||||
}
|
||||
|
||||
|
||||
exports.get_latest_calls = function (req, res) {
|
||||
var filter_code = req.query["filter-code"];
|
||||
|
||||
@@ -105,6 +105,7 @@ app.get('/:shortName/calls/latest', calls.get_latest_calls);
|
||||
app.get('/:shortName/calls/next', calls.get_next_calls);
|
||||
app.get('/:shortName/calls/newer', calls.get_newer_calls);
|
||||
app.get('/:shortName/calls/older', calls.get_older_calls);
|
||||
app.get('/:shortName/calls/date', calls.get_date_calls);
|
||||
app.get('/:shortName/calls/:time/older', calls.get_iphone_calls);
|
||||
app.get('/:shortName/calls', calls.get_calls);
|
||||
|
||||
|
||||
@@ -49,12 +49,14 @@ function CallPlayer(props) {
|
||||
const [currentCall, setCurrentCall] = useState(false);
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
const [silenceCount, setSilenceCount] = useState(0);
|
||||
const [selectedInitialCall, setSelectedInitialCall] = useState(false);
|
||||
const { callLink, callDownload, callTweet } = useCallLink(currentCall)
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const stickyRef = useRef(); // lets us get the Y Scroll offset for the Call List
|
||||
const positionRef = useRef(); // lets us get the Y Scroll offset for the Call List
|
||||
const shouldPlayAddCallRef = useRef(); // we need to do this to make the current value of isPlaying available in the socket message callback
|
||||
//const selectedInitialCall = useRef(false); // allows you to track if you have already selected the Initial Call - you only want to do this once
|
||||
shouldPlayAddCallRef.current = (!isPlaying && autoPlay) ? true : false;
|
||||
|
||||
let currentCallId = false;
|
||||
@@ -122,9 +124,24 @@ function CallPlayer(props) {
|
||||
}
|
||||
}, [loadOlderInView]);
|
||||
|
||||
// This handles when a Call is specified in the URI
|
||||
useEffect(() => {
|
||||
if (props.initialCallId && callsData) {
|
||||
const call = callsData.entities[props.initialCallId];
|
||||
if (call && !selectedInitialCall) {
|
||||
const time = new Date(call.time);
|
||||
|
||||
console.log("Playing Initial Call: " + call._id + " Start Time: " + time.toLocaleTimeString() );
|
||||
setIsPlaying(true);
|
||||
setCurrentCall(call);
|
||||
setSelectedInitialCall(true); // signals that it has selected the initial call - you only want to do this once
|
||||
dispatch(playedCall(call._id));
|
||||
}
|
||||
}
|
||||
}, [props.initialCallId, callsData])
|
||||
|
||||
// Triggered when a new call is selected in the parent component.
|
||||
// This happens in 2 scenarios: when a call is specified in the URI or when a new call comes over the socket
|
||||
// This happens when a new call comes over the socket
|
||||
// When a call is set to CurrentCall, it will automatically start playing
|
||||
// we should only set the selectCallId to be the current call when AutoPlay is selected
|
||||
// and when there isn't another call already playing
|
||||
|
||||
@@ -43,6 +43,7 @@ function Calls(props) {
|
||||
const [activityVisible, setActivityVisible] = useState(false);
|
||||
const [isConnected, setIsConnected] = useState(socket.connected);
|
||||
const [selectCallId, setSelectCallId] = useState(false);
|
||||
const [initialCallId, setInitialCallId] = useState(false);
|
||||
const [live, setLive] = useState(true);
|
||||
|
||||
const navigate = useNavigate();
|
||||
@@ -174,6 +175,12 @@ function Calls(props) {
|
||||
|
||||
}
|
||||
|
||||
if (initialCallId) {
|
||||
if (search.length !== 1) {
|
||||
search = search + '&';
|
||||
}
|
||||
search = search + `call-id=${initialCallId}`;
|
||||
}
|
||||
if (filterDate) {
|
||||
if (search.length !== 1) {
|
||||
search = search + '&';
|
||||
@@ -280,7 +287,7 @@ function Calls(props) {
|
||||
// is this just for one call?
|
||||
if (uri.hasOwnProperty('call-id')) {
|
||||
const _id = uri['call-id'];
|
||||
setSelectCallId(_id);
|
||||
setInitialCallId(_id);
|
||||
setAutoPlay(false);
|
||||
setLive(false);
|
||||
if (!urlOptions) setUrlOptions(true);
|
||||
@@ -344,7 +351,9 @@ function Calls(props) {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getCalls({}));
|
||||
|
||||
dispatch(getCalls({}));
|
||||
|
||||
if (live && isConnected) {
|
||||
startSocket();
|
||||
}
|
||||
@@ -354,7 +363,7 @@ function Calls(props) {
|
||||
// Update the Browser URI when any relevant values change
|
||||
useEffect(() => {
|
||||
updateUri();
|
||||
}, [filterGroupId, filterTalkgroups, filterType, filterDate, filterStarred, selectCallId])
|
||||
}, [filterGroupId, filterTalkgroups, filterType, filterDate, filterStarred, selectCallId, initialCallId])
|
||||
|
||||
useEffect(() => {
|
||||
if (!urlOptions && groupsData && (groupsData.length > 0)) {
|
||||
@@ -438,7 +447,7 @@ function Calls(props) {
|
||||
</Menu>
|
||||
{activityVisible
|
||||
? <Activity navigate={handleActivityNavigate} />
|
||||
: <CallPlayer callsData={callsData} selectCallId={selectCallId} handleNewer={handleNewer} handleOlder={handleOlder} />
|
||||
: <CallPlayer callsData={callsData} selectCallId={selectCallId} initialCallId={initialCallId} handleNewer={handleNewer} handleOlder={handleOlder} />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
import React, { useMemo, useCallback } from 'react';
|
||||
import { AreaClosed, Line, Bar } from '@visx/shape';
|
||||
import appleStock, { AppleStock } from '@visx/mock-data/lib/mocks/appleStock';
|
||||
import { curveMonotoneX } from '@visx/curve';
|
||||
import { GridRows, GridColumns } from '@visx/grid';
|
||||
import { scaleTime, scaleLinear } from '@visx/scale';
|
||||
import { withTooltip, Tooltip, TooltipWithBounds, defaultStyles } from '@visx/tooltip';
|
||||
import { WithTooltipProvidedProps } from '@visx/tooltip/lib/enhancers/withTooltip';
|
||||
import { localPoint } from '@visx/event';
|
||||
import { LinearGradient } from '@visx/gradient';
|
||||
import { max, extent, bisector } from 'd3-array';
|
||||
import { timeFormat } from 'd3-time-format';
|
||||
|
||||
type TooltipData = AppleStock;
|
||||
|
||||
const stock = appleStock.slice(800);
|
||||
export const background = '#3b6978';
|
||||
export const background2 = '#204051';
|
||||
export const accentColor = '#edffea';
|
||||
export const accentColorDark = '#75daad';
|
||||
const tooltipStyles = {
|
||||
...defaultStyles,
|
||||
background,
|
||||
border: '1px solid white',
|
||||
color: 'white',
|
||||
};
|
||||
|
||||
// util
|
||||
const formatDate = timeFormat("%b %d, '%y");
|
||||
|
||||
// accessors
|
||||
const getDate = (d: AppleStock) => new Date(d.date);
|
||||
const getStockValue = (d: AppleStock) => d.close;
|
||||
const bisectDate = bisector<AppleStock, Date>((d) => new Date(d.date)).left;
|
||||
|
||||
export type AreaProps = {
|
||||
width: number;
|
||||
height: number;
|
||||
margin?: { top: number; right: number; bottom: number; left: number };
|
||||
};
|
||||
|
||||
export default withTooltip<AreaProps, TooltipData>(
|
||||
({
|
||||
width,
|
||||
height,
|
||||
margin = { top: 0, right: 0, bottom: 0, left: 0 },
|
||||
showTooltip,
|
||||
hideTooltip,
|
||||
tooltipData,
|
||||
tooltipTop = 0,
|
||||
tooltipLeft = 0,
|
||||
}: AreaProps & WithTooltipProvidedProps<TooltipData>) => {
|
||||
if (width < 10) return null;
|
||||
|
||||
// bounds
|
||||
const innerWidth = width - margin.left - margin.right;
|
||||
const innerHeight = height - margin.top - margin.bottom;
|
||||
|
||||
// scales
|
||||
const dateScale = useMemo(
|
||||
() =>
|
||||
scaleTime({
|
||||
range: [margin.left, innerWidth + margin.left],
|
||||
domain: extent(stock, getDate) as [Date, Date],
|
||||
}),
|
||||
[innerWidth, margin.left],
|
||||
);
|
||||
const stockValueScale = useMemo(
|
||||
() =>
|
||||
scaleLinear({
|
||||
range: [innerHeight + margin.top, margin.top],
|
||||
domain: [0, (max(stock, getStockValue) || 0) + innerHeight / 3],
|
||||
nice: true,
|
||||
}),
|
||||
[margin.top, innerHeight],
|
||||
);
|
||||
|
||||
// tooltip handler
|
||||
const handleTooltip = useCallback(
|
||||
(event: React.TouchEvent<SVGRectElement> | React.MouseEvent<SVGRectElement>) => {
|
||||
const { x } = localPoint(event) || { x: 0 };
|
||||
const x0 = dateScale.invert(x);
|
||||
const index = bisectDate(stock, x0, 1);
|
||||
const d0 = stock[index - 1];
|
||||
const d1 = stock[index];
|
||||
let d = d0;
|
||||
if (d1 && getDate(d1)) {
|
||||
d = x0.valueOf() - getDate(d0).valueOf() > getDate(d1).valueOf() - x0.valueOf() ? d1 : d0;
|
||||
}
|
||||
showTooltip({
|
||||
tooltipData: d,
|
||||
tooltipLeft: x,
|
||||
tooltipTop: stockValueScale(getStockValue(d)),
|
||||
});
|
||||
},
|
||||
[showTooltip, stockValueScale, dateScale],
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<svg width={width} height={height}>
|
||||
<rect
|
||||
x={0}
|
||||
y={0}
|
||||
width={width}
|
||||
height={height}
|
||||
fill="url(#area-background-gradient)"
|
||||
rx={14}
|
||||
/>
|
||||
<LinearGradient id="area-background-gradient" from={background} to={background2} />
|
||||
<LinearGradient id="area-gradient" from={accentColor} to={accentColor} toOpacity={0.1} />
|
||||
<GridRows
|
||||
left={margin.left}
|
||||
scale={stockValueScale}
|
||||
width={innerWidth}
|
||||
strokeDasharray="1,3"
|
||||
stroke={accentColor}
|
||||
strokeOpacity={0}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<GridColumns
|
||||
top={margin.top}
|
||||
scale={dateScale}
|
||||
height={innerHeight}
|
||||
strokeDasharray="1,3"
|
||||
stroke={accentColor}
|
||||
strokeOpacity={0.2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<AreaClosed<AppleStock>
|
||||
data={stock}
|
||||
x={(d) => dateScale(getDate(d)) ?? 0}
|
||||
y={(d) => stockValueScale(getStockValue(d)) ?? 0}
|
||||
yScale={stockValueScale}
|
||||
strokeWidth={1}
|
||||
stroke="url(#area-gradient)"
|
||||
fill="url(#area-gradient)"
|
||||
curve={curveMonotoneX}
|
||||
/>
|
||||
<Bar
|
||||
x={margin.left}
|
||||
y={margin.top}
|
||||
width={innerWidth}
|
||||
height={innerHeight}
|
||||
fill="transparent"
|
||||
rx={14}
|
||||
onTouchStart={handleTooltip}
|
||||
onTouchMove={handleTooltip}
|
||||
onMouseMove={handleTooltip}
|
||||
onMouseLeave={() => hideTooltip()}
|
||||
/>
|
||||
{tooltipData && (
|
||||
<g>
|
||||
<Line
|
||||
from={{ x: tooltipLeft, y: margin.top }}
|
||||
to={{ x: tooltipLeft, y: innerHeight + margin.top }}
|
||||
stroke={accentColorDark}
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
strokeDasharray="5,2"
|
||||
/>
|
||||
<circle
|
||||
cx={tooltipLeft}
|
||||
cy={tooltipTop + 1}
|
||||
r={4}
|
||||
fill="black"
|
||||
fillOpacity={0.1}
|
||||
stroke="black"
|
||||
strokeOpacity={0.1}
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<circle
|
||||
cx={tooltipLeft}
|
||||
cy={tooltipTop}
|
||||
r={4}
|
||||
fill={accentColorDark}
|
||||
stroke="white"
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
</g>
|
||||
)}
|
||||
</svg>
|
||||
{tooltipData && (
|
||||
<div>
|
||||
<TooltipWithBounds
|
||||
key={Math.random()}
|
||||
top={tooltipTop - 12}
|
||||
left={tooltipLeft + 12}
|
||||
style={tooltipStyles}
|
||||
>
|
||||
{`$${getStockValue(tooltipData)}`}
|
||||
</TooltipWithBounds>
|
||||
<Tooltip
|
||||
top={innerHeight + margin.top - 14}
|
||||
left={tooltipLeft}
|
||||
style={{
|
||||
...defaultStyles,
|
||||
minWidth: 72,
|
||||
textAlign: 'center',
|
||||
transform: 'translateX(-50%)',
|
||||
}}
|
||||
>
|
||||
{formatDate(getDate(tooltipData))}
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import React, { useEffect, useLayoutEffect, useRef } from "react";
|
||||
import { useParams } from 'react-router-dom';
|
||||
import CallItem from "./CallItem";
|
||||
import {
|
||||
@@ -22,13 +22,13 @@ const ListCalls = (props) => {
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
useLayoutEffect(() => {
|
||||
if (activeCallRef.current && centerCall) {
|
||||
activeCallRef.current.scrollIntoView({
|
||||
block: "center",
|
||||
});
|
||||
}
|
||||
},[activeCallId]);
|
||||
},[activeCallId, activeCallRef.current]);
|
||||
|
||||
const callsData = props.callsData;
|
||||
return (
|
||||
|
||||
@@ -19,19 +19,19 @@ const MediaPlayer = (props) => {
|
||||
const parentHandlePlayPause = props.onPlayPause
|
||||
const playSilence = props.playSilence;
|
||||
|
||||
const handlePause = () => { setIsPlaying(false); }
|
||||
const handlePlay = () => { setIsPlaying(true); }
|
||||
const playPause = () => {
|
||||
const audio = audioRef.current.audioEl.current;
|
||||
if (isPlaying) {
|
||||
setIsPlaying(false);
|
||||
parentHandlePlayPause(false);
|
||||
audio.pause();
|
||||
} else {
|
||||
setIsPlaying(true);
|
||||
const handlePause = () => { setIsPlaying(false); }
|
||||
const handlePlay = () => { setIsPlaying(true); }
|
||||
const playPause = () => {
|
||||
const audio = audioRef.current.audioEl.current;
|
||||
if (isPlaying) {
|
||||
setIsPlaying(false);
|
||||
parentHandlePlayPause(false);
|
||||
audio.pause();
|
||||
} else {
|
||||
setIsPlaying(true);
|
||||
parentHandlePlayPause(true);
|
||||
audio.play();
|
||||
}
|
||||
audio.play();
|
||||
}
|
||||
}
|
||||
|
||||
const call = props.call;
|
||||
@@ -41,7 +41,7 @@ const MediaPlayer = (props) => {
|
||||
const audio = audioRef.current.audioEl.current;
|
||||
const onEnded = props.onEnded;
|
||||
setSourceIndex(0);
|
||||
if (call) {
|
||||
if (call ) {
|
||||
audio.src = call.url;
|
||||
const playPromise = audio.play();
|
||||
|
||||
@@ -53,7 +53,7 @@ const MediaPlayer = (props) => {
|
||||
}).catch(function (error) {
|
||||
console.log("Automatic playback failed: " + error);
|
||||
handlePause();
|
||||
onEnded();
|
||||
//onEnded();
|
||||
// Show a UI element to let the user manually start playback.
|
||||
});
|
||||
} else {
|
||||
@@ -75,22 +75,22 @@ const MediaPlayer = (props) => {
|
||||
{ src: '/android-chrome-192x192.png', sizes: '512x512', type: 'image/png' },
|
||||
]
|
||||
});
|
||||
audio.src = "data:audio/mpeg;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4Ljc2LjEwMAAAAAAAAAAAAAAA/+M4wAAAAAAAAAAAAEluZm8AAAAPAAAAAwAAAbAAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////////////////////////////////////////AAAAAExhdmM1OC4xMwAAAAAAAAAAAAAAACQDkAAAAAAAAAGw9wrNaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+MYxAAAAANIAAAAAExBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxDsAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxHYAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV";
|
||||
const playPromise = audio.play();
|
||||
audio.src = "data:audio/mpeg;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4Ljc2LjEwMAAAAAAAAAAAAAAA/+M4wAAAAAAAAAAAAEluZm8AAAAPAAAAAwAAAbAAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////////////////////////////////////////AAAAAExhdmM1OC4xMwAAAAAAAAAAAAAAACQDkAAAAAAAAAGw9wrNaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+MYxAAAAANIAAAAAExBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxDsAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxHYAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV";
|
||||
const playPromise = audio.play();
|
||||
|
||||
// In browsers that don’t yet support this functionality,
|
||||
// playPromise won’t be defined.
|
||||
if (playPromise !== undefined) {
|
||||
playPromise.then(function () {
|
||||
// In browsers that don’t yet support this functionality,
|
||||
// playPromise won’t be defined.
|
||||
if (playPromise !== undefined) {
|
||||
playPromise.then(function () {
|
||||
|
||||
}).catch(function (error) {
|
||||
console.log("Automatic playback failed: " + error);
|
||||
// Show a UI element to let the user manually start playback.
|
||||
});
|
||||
} else {
|
||||
audio.src = false;
|
||||
}
|
||||
|
||||
}).catch(function (error) {
|
||||
console.log("Automatic playback failed: " + error);
|
||||
// Show a UI element to let the user manually start playback.
|
||||
});
|
||||
} else {
|
||||
audio.src = false;
|
||||
}
|
||||
|
||||
}, [playSilence]);
|
||||
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ function SystemCard (props) {
|
||||
<Grid.Row>
|
||||
<Grid.Column >
|
||||
{system.screenName && <Label size="mini"><Icon name='user' /> {system.screenName}</Label>}
|
||||
{/*system.allowContact && <Label size="mini" onClick={handleContactClick}><Icon name='mail' />Message</Label>*/}
|
||||
{system.allowContact && <Label size="mini" onClick={handleContactClick}><Icon name='mail' />Message</Label>}
|
||||
</Grid.Column>
|
||||
</Grid.Row>
|
||||
<Grid.Row>
|
||||
|
||||
@@ -85,7 +85,7 @@ const initialState = {
|
||||
params["time"] = date;
|
||||
} else {
|
||||
if (filterDate){
|
||||
url = url + '/older'
|
||||
url = url + '/date'
|
||||
params["time"] = filterDate;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user