Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
},
"scripts": {
"clean": "rm -rf public/assets public/index.html",
"clean-w": "rmdir /s /q public\\assets && del /f /q public\\index.html",
"build": "npm run clean && npm run build:bundle",
"build-w": "npm run clean-w && npm run build:bundle",
"build:bundle": "webpack --progress",
"build:production": "npm run --prod build",
"dev-server": "npm run build && webpack-dev-server --inline --hot",
"dev-server-w": "npm run build-w && webpack-dev-server --inline --hot",
"flow": "flow check",
"lint": "eslint webpack.config.js --ext .js --ext .jsx src"
},
Expand Down
1 change: 1 addition & 0 deletions src/INITIAL_STATE.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
chatSize: localStorage ? Number(localStorage.getItem('chatSize')) || 400 : 400,
showChat: localStorage ? !(localStorage.getItem('showChat') === 'false') : true,
showHeader: true,
imageModalSrc: null,
showFooter: true,
},
self: {
Expand Down
8 changes: 8 additions & 0 deletions src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ export const showHeader = value => dispatch => {
});
};

export const IMAGE_MODAL_SRC = Symbol('IMAGE_MODAL_SRC');
export const imageModalSrc = value => dispatch => {
dispatch({
type: IMAGE_MODAL_SRC,
payload: value,
});
};

export const SHOW_FOOTER = Symbol('SHOW_FOOTER');
export const showFooter = value => dispatch => {
dispatch({
Expand Down
63 changes: 63 additions & 0 deletions src/components/ImagePreviewModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// @flow

import React from "react";
import cs from "classnames";

import "../css/ImageModal";
import { connect } from "react-redux";
import { imageModalSrc } from "../actions";

const ImageModal = ({ dispatch, src, onClose }) => (
<div
className="image-modal"
tabIndex={-1}
onClick={onClose}
onKeyDown={(e) => {
if (e.key === "Escape") dispatch(imageModalSrc(null));
}}
>
<div
className="image-modal__backdrop"
onClick={() => {
dispatch(imageModalSrc(null));
}}
></div>

<div className="image-modal__content" onClick={(e) => e.stopPropagation()}>
<div className="image-modal__toolbar">
<button
className="image-modal__btn button-orange"
tabIndex={0}
onClick={() => {
window.open(src,'_blank')
}}
>
<span className="glyphicon glyphicon-new-window" />
</button>
<button
className="image-modal__btn button-orange"
tabIndex={0}
onClick={() => navigator.clipboard.writeText(src)}
>
<span className="glyphicon glyphicon-duplicate" />
</button>

<button
className="image-modal__btn image-modal__btn--close button-orange"
aria-label="Close"
tabIndex={0}
autoFocus
onClick={() => {
dispatch(imageModalSrc(null));
}}
>
<span className="glyphicon glyphicon-remove" />
</button>
</div>

<img src={src} alt="" />
</div>
</div>
);

export default connect()(ImageModal);
11 changes: 10 additions & 1 deletion src/components/RoutesWithChat.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Header from './Header';
import Footer from './Footer';

import CustomScrollbar from './CustomScrollbar';
import ImageModal from './ImagePreviewModal';

import '../css/Stream';

Expand All @@ -22,7 +23,7 @@ import {
showHeader as headerFunc
} from '../actions';

export const RoutesWithChat = ({showHeader, showFooter, setChatSize, showChat, showLeftChat=false, chatClosed, chatSize, headerFunc}) =>
export const RoutesWithChat = ({showHeader, showFooter, setChatSize, showChat, showLeftChat=false, chatClosed, chatSize, headerFunc, imageModalSrc}) =>
{
let left = (
<div className='flex-shrink-0 stream-embed' style={{ width: chatClosed ? '100%' : `calc(100% - ${chatSize}px)`, height: chatClosed ? '100%' : '', display: 'flex', flexDirection: 'column'}}>
Expand Down Expand Up @@ -53,6 +54,11 @@ export const RoutesWithChat = ({showHeader, showFooter, setChatSize, showChat, s
<div title={showHeader ? "Close Header" : "Open Header"} className= {showHeader ?"close-header-btn" : 'open-header-btn'}>
<span className={showHeader ? 'close-header-caret': 'open-header-caret'} onClick={() => showHeader ? headerFunc(false) : headerFunc(true)}>&#8250;</span>
</div>
{imageModalSrc && (
<ImageModal
src={imageModalSrc}
/>
)}
<Resizeable
className='flex-grow-1 flex-column flex-lg-row'
onResize={e => {
Expand Down Expand Up @@ -80,6 +86,8 @@ RoutesWithChat.propTypes = {
showLeftChat: PropTypes.bool,
chatClosed: PropTypes.bool,

imageModalSrc: PropTypes.string,

chatSize: PropTypes.number.isRequired,

setChatSize: PropTypes.func.isRequired,
Expand All @@ -96,6 +104,7 @@ export default compose(
showLeftChat: idx(state, _ => _.self.profile.data.left_chat),
chatClosed: !state.ui.showChat || !state.self.isLoggedIn,
headerClosed: !state.ui.showHeader,
imageModalSrc: state.ui.imageModalSrc,
}),
{
setChatSize,
Expand Down
45 changes: 45 additions & 0 deletions src/css/ImageModal.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// modal when image is opened
.image-modal {
position: fixed;
inset: 0;
z-index: 9999;
}

.image-modal__backdrop {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.8);
}

.image-modal__content {
height: 100%;
place-items: end;
margin-left: auto;
margin-right: auto;
display: flex;
justify-content: center;
flex-flow: column;
width: max-content;
z-index: 100;
position: relative;
}

.image-modal__btn {
margin-left: 15px;
cursor: pointer;
}

.image-modal__toolbar {
margin-bottom: 10px;
button {
span {
font-size: 25px;
}
}
}

.image-modal img {
max-width: 90vw;
max-height: 90vh;
user-select: none;
}
9 changes: 9 additions & 0 deletions src/css/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ a {
}
}

.button-orange{
border: none;
background-color: transparent;
color: $rustle-orange;
&:hover, &:focus {
color: darken($rustle-orange, 20%);
}
}

.form-control, .form-control, .btn-group > .navbar-btn, .input-group-btn > .btn {
background-color: #222;
color: #fff;
Expand Down
6 changes: 6 additions & 0 deletions src/reducers/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
SHOW_CHAT,
SHOW_HEADER,
SHOW_FOOTER,
IMAGE_MODAL_SRC,
} from '../actions';
import { actions } from '../actions/websocket';

Expand Down Expand Up @@ -38,6 +39,11 @@ function uiReducer(state = INITIAL_STATE.ui, action) {
...state,
showHeader: action.payload,
};
case IMAGE_MODAL_SRC:
return {
...state,
imageModalSrc: action.payload,
};
case SHOW_FOOTER:
return {
...state,
Expand Down
1 change: 1 addition & 0 deletions src/redux/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ export type State = {|
+showChat: boolean,
+showHeader: boolean,
+showFooter: boolean,
+imageModalSrc: string,
|}
|};
Loading