Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Tweaks #158

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
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
18 changes: 18 additions & 0 deletions Config.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,21 @@ export Config =
defaultSort:
key: 'title' # see client/RoomList.coffee for other options
reverse: false

## Whether to have a compact room list by default
default_compact: false

## Whether to hide the room creation widget at the bottom of the room list by default
default_hideCreate: false

## Whether to hide the room search widget in the room list by default
default_hideSearch: false

## Whether to hide the starred rooms accordion in the room list by default
default_hideStarred: false

## Whether to hide the title / header at the top of the room list by default
default_hideTitle: false

## Whether to hide the title / button bar at the top of the room tabset by default
default_hideRoombar: false
4 changes: 2 additions & 2 deletions client/App.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {BrowserRouter as Router, Switch, Route} from 'react-router-dom'

import {FrontPage} from './FrontPage'
import {Meeting} from './Meeting'
import {useDark} from './Settings'
import {useUI} from './Settings'
import {Redirect} from './lib/Redirect'

export App = React.memo ->
Expand Down Expand Up @@ -31,7 +31,7 @@ export AppRouter = React.memo ->
AppRouter.displayName = 'AppRouter'

export DarkClass = React.memo ->
dark = useDark()
dark = useUI('dark')
if dark
document.body.classList.add 'dark'
else
Expand Down
4 changes: 2 additions & 2 deletions client/FrontPage.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {Button, ButtonGroup, Form, Jumbotron} from 'react-bootstrap'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
import {faGithub} from '@fortawesome/free-brands-svg-icons'

import {Dark} from './Settings'
import {UIToggle} from './Settings'
import {setMeetingSecret} from './MeetingSecret'
import {VisitedMeetings} from './VisitedMeetings'
import {getUpdator} from './lib/presenceId'
Expand Down Expand Up @@ -45,7 +45,7 @@ export FrontPage = React.memo ->
<p/>
<VisitedMeetings/>
<p/>
<Dark/>
<UIToggle name="dark"/>
<p/>
<ButtonGroup className="flex-wrap">
<Button variant="info" as="a" href={homepage}>
Expand Down
95 changes: 49 additions & 46 deletions client/Room.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {TabNew} from './TabNew'
import {TabIFrame} from './TabIFrame'
import {TabJitsi} from './TabJitsi'
import {TabZoom} from './TabZoom'
import {getUI} from './Settings'

tabTitle = (tab) ->
tab.title or 'Untitled'
Expand Down Expand Up @@ -475,57 +476,59 @@ export Room = React.memo ({loading, roomId, onClose, enableMaximize, maximized,
</OverlayTrigger>

<div className="Room" onKeyDown={onKeyDown}>
<div className="header">
{leaveRoom 'leading icon-button'}
<RoomTitle room={room} roomId={roomId}/>
<OverlayTrigger placement="bottom" overlay={(props) ->
<Tooltip {...props}>Copy room link to clipboard</Tooltip>
}>
<div aria-label="Copy room link to clipboard" onClick={roomLink}
className="flexlayout__tab_button_trailing">
<FontAwesomeIcon icon={clipboardLink}/>
</div>
</OverlayTrigger>
{if room?
label = "#{if showArchived then "Hide" else "Show"} Archived Tabs"
{unless getUI('hideroombar')
<div className="header">
{leaveRoom 'leading icon-button'}
<RoomTitle room={room} roomId={roomId}/>
<OverlayTrigger placement="bottom" overlay={(props) ->
<Tooltip {...props}>
{label}
<div className="small">
Currently {unless showArchived then <b>not</b>} showing archived tabs.
</div>
</Tooltip>
<Tooltip {...props}>Copy room link to clipboard</Tooltip>
}>
<div aria-label={label} onClick={-> setShowArchived not showArchived}
<div aria-label="Copy room link to clipboard" onClick={roomLink}
className="flexlayout__tab_button_trailing">
<FontAwesomeIcon icon={if showArchived then faEye else faEyeSlash}/>
<FontAwesomeIcon icon={clipboardLink}/>
</div>
</OverlayTrigger>
}
{if room? and authorized
<ArchiveButton noun="room" className="flexlayout__tab_button_trailing"
archived={room?.archived} onClick={archiveRoom}
help="Archived rooms can still be viewed and restored from the list at the bottom of the room list."/>
}
{if room? and admin
<DeleteButton noun="room" onClick={deleteRoom}
className="flexlayout__tab_button_trailing admin"/>
}
{if room? and admin
<ProtectButton className="flexlayout__tab_button_trailing admin"
protected={room?.protected} onClick={protectRoom}/>
}
{leaveRoom 'trailing'}
{if enableMaximize
<div onClick={onMaximize} className="flexlayout__tab_button_trailing">
{if maximized
FlexLayout.icons('room').restore
else
FlexLayout.icons('room').maximize
}
</div>
}
</div>
{if room?
label = "#{if showArchived then "Hide" else "Show"} Archived Tabs"
<OverlayTrigger placement="bottom" overlay={(props) ->
<Tooltip {...props}>
{label}
<div className="small">
Currently {unless showArchived then <b>not</b>} showing archived tabs.
</div>
</Tooltip>
}>
<div aria-label={label} onClick={-> setShowArchived not showArchived}
className="flexlayout__tab_button_trailing">
<FontAwesomeIcon icon={if showArchived then faEye else faEyeSlash}/>
</div>
</OverlayTrigger>
}
{if room? and authorized
<ArchiveButton noun="room" className="flexlayout__tab_button_trailing"
archived={room?.archived} onClick={archiveRoom}
help="Archived rooms can still be viewed and restored from the list at the bottom of the room list."/>
}
{if room? and admin
<DeleteButton noun="room" onClick={deleteRoom}
className="flexlayout__tab_button_trailing admin"/>
}
{if room? and admin
<ProtectButton className="flexlayout__tab_button_trailing admin"
protected={room?.protected} onClick={protectRoom}/>
}
{leaveRoom 'trailing'}
{if enableMaximize
<div onClick={onMaximize} className="flexlayout__tab_button_trailing">
{if maximized
FlexLayout.icons('room').restore
else
FlexLayout.icons('room').maximize
}
</div>
}
</div>
}
<div className="container">
{if loading or not model? ### Post-loading, useEffect needs a tick to set model ###
<Loading/>
Expand Down
46 changes: 27 additions & 19 deletions client/RoomList.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {MeetingContext} from './Meeting'
import {useMeetingAdmin} from './MeetingSecret'
import {Name} from './Name'
import {useAdminVisit} from './Settings'
import {getUI} from './Settings'
import {Warnings} from './Warnings'
import {getPresenceId, getUpdator} from './lib/presenceId'
import {formatTimeDelta, formatDateTime} from './lib/dates'
Expand Down Expand Up @@ -151,7 +152,9 @@ export RoomList = React.memo ({loading, model, extraData, updateTab}) ->

<div className="d-flex flex-column h-100 RoomList" onKeyDown={onKeyDown}>
<div className="sidebar flex-grow-1 overflow-auto pb-2" ref={roomList}>
<Header/>
{unless getUI('hideTitle')
<Header/>
}
<Warnings/>
<Name/>
{if starredHasOld
Expand Down Expand Up @@ -185,7 +188,7 @@ export RoomList = React.memo ({loading, model, extraData, updateTab}) ->
</div>
</Alert>
}
{if rooms.length > 0
{if rooms.length > 0 and not getUI('hideSearch')
<Accordion>
<Card>
<CardToggle eventKey="0">
Expand Down Expand Up @@ -246,22 +249,24 @@ export RoomList = React.memo ({loading, model, extraData, updateTab}) ->
No rooms in this meeting.
</Alert>
}
<Sublist {...{sortedRooms, presenceByRoom, selected, selectRoom, model}}
heading="Your Starred Rooms:" startClosed search={searchDebounce}
filter={(room) -> findMyPresence(presenceByRoom[room._id]).starred}
className="starred">
<OverlayTrigger placement="top" overlay={(props) ->
<Tooltip {...props}>
Unstar all rooms
</Tooltip>
}>
<div className="text-center">
<Button size="sm" variant="outline-warning" onClick={clearStars}>
Clear Stars
</Button>
</div>
</OverlayTrigger>
</Sublist>
{unless getUI('hideStarred')
<Sublist {...{sortedRooms, presenceByRoom, selected, selectRoom, model}}
heading="Your Starred Rooms:" startClosed search={searchDebounce}
filter={(room) -> findMyPresence(presenceByRoom[room._id]).starred}
className="starred">
<OverlayTrigger placement="top" overlay={(props) ->
<Tooltip {...props}>
Unstar all rooms
</Tooltip>
}>
<div className="text-center">
<Button size="sm" variant="outline-warning" onClick={clearStars}>
Clear Stars
</Button>
</div>
</OverlayTrigger>
</Sublist>
}
<Sublist {...{sortedRooms, presenceByRoom, selected, selectRoom, model}}
heading="Available Rooms:" search={searchDebounce} className="available"
filter={(room) -> not room.archived and
Expand All @@ -272,7 +277,9 @@ export RoomList = React.memo ({loading, model, extraData, updateTab}) ->
filter={(room) -> room.archived and
(not nonempty or hasJoined(room) or selected == room._id)}/>
</div>
<RoomNew selectRoom={selectRoom}/>
{unless getUI('hideCreate')
<RoomNew selectRoom={selectRoom}/>
}
</div>
RoomList.displayName = 'RoomList'

Expand Down Expand Up @@ -368,6 +375,7 @@ export RoomInfo = React.memo ({room, search, presence, selected, selectRoom, lea
roomInfoClass += " presence-#{type}" for type of myPresence
roomInfoClass += " selected" if selected
roomInfoClass += " archived" if room.archived
roomInfoClass += " compact" if getUI("compact")
adminVisit = useAdminVisit()

onClick = (force) -> (e) ->
Expand Down
45 changes: 33 additions & 12 deletions client/Settings.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Card, Form} from 'react-bootstrap'
import {LocalStorageVar, StorageDict} from './lib/useLocalStorage'
import {MeetingTitle} from './MeetingTitle'
import {MeetingSecret, useMeetingAdmin} from './MeetingSecret'
import {Config} from '/Config'

export Settings = React.memo ->
admin = useMeetingAdmin()
Expand All @@ -13,7 +14,7 @@ export Settings = React.memo ->
<Card.Body>
<Card.Title as="h3">Settings</Card.Title>
<Form>
<Dark/>
<UIToggles/>
</Form>
</Card.Body>
</Card>
Expand All @@ -34,17 +35,37 @@ export Settings = React.memo ->
</>
Settings.displayName = 'Settings'

darkVar = new LocalStorageVar 'dark', ->
window.matchMedia('(prefers-color-scheme: dark)').matches
, sync: true
export useDark = -> darkVar.use()
export getDark = -> darkVar.get()

export Dark = React.memo ->
dark = useDark()
<Form.Switch id="dark" label="Dark Mode" checked={dark}
onChange={(e) -> darkVar.set e.target.checked}/>
Dark.displayName = 'Dark'
uiVars = {}
uiLabels = {}
export useUI = (name) -> uiVars[name].use()
export getUI = (name) -> uiVars[name].get()

addUIVar = (name, label, init) ->
unless init?
init = ->
Config["default_" + name]
uiVars[name] = new LocalStorageVar name, init, sync: true
uiLabels[name] = label

addUIVar('dark', 'Dark Mode', -> window.matchMedia('(prefers-color-scheme: dark)').matches)
addUIVar('compact', 'Compact Room List')
addUIVar('hideCreate', 'Hide Room Creation Widget')
addUIVar('hideSearch', 'Hide Room Search Widget')
addUIVar('hideStarred', 'Hide Starred Rooms Accordion')
addUIVar('hideTitle', 'Hide Meeting Title')
addUIVar('hideRoombar', 'Hide Room Menubar')

UIToggles = React.memo ->
for name, label of uiLabels
<UIToggle name={name} key={name}/>
UIToggles.displayName = 'UIToggles'

export UIToggle = React.memo ({name}) ->
value = useUI(name)
label = uiLabels[name]
<Form.Switch id={name} label={label} checked={value}
onChange={(e) -> uiVars[name].set e.target.checked}/>
UIToggle.displayName = 'UIToggle'

adminVisitVars = new StorageDict LocalStorageVar,
'adminVisit', false, sync: true
Expand Down
4 changes: 2 additions & 2 deletions client/TabIFrame.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {useTracker} from 'meteor/react-meteor-data'
import useEventListener from '@use-it/event-listener'

import {useName} from './Name'
import {useDark} from './Settings'
import {useUI} from './Settings'
import {Tabs} from '/lib/tabs'

###
Expand Down Expand Up @@ -47,7 +47,7 @@ export TabIFrame = React.memo ({tabId}) ->

## Send name to tab if it speaks coop protocol
name = useName()
dark = useDark()
dark = useUI("dark")
[coop, setCoop] = useState 0
useEventListener 'message', (e) ->
return unless ref.current
Expand Down
4 changes: 2 additions & 2 deletions client/TabJitsi.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {Alert, Button, Card} from 'react-bootstrap'

import {Loading} from './Loading'
import {useName} from './Name'
import {getDark} from './Settings'
import {getUI} from './Settings'
import {Tabs} from '/lib/tabs'

## Remember the state of the last Jitsi call, except when there are no calls
Expand Down Expand Up @@ -63,7 +63,7 @@ export TabJitsi = React.memo ({tabId, room}) ->
interfaceConfigOverwrite:
# See https://github.com/jitsi/jitsi-meet/blob/master/interface_config.js
DEFAULT_BACKGROUND:
if getDark() then '#111' else '#474747'
if getUI('dark') then '#111' else '#474747'
DISABLE_VIDEO_BACKGROUND: true
TOOLBAR_BUTTONS: [
'microphone', 'camera', 'closedcaptions', 'desktop',
Expand Down
3 changes: 3 additions & 0 deletions client/main.styl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ nav
margin-top: 0.75rem
font-size: 80%
cursor: pointer
.compact
padding: 0.25rem 1rem 0.25rem 0.25rem
font-size: 80%
// Give dismissible alerts normal margin; instead use float for close button
.alert-dismissible
padding-right: 1.25rem
Expand Down