Skip to content

Commit

Permalink
Added many UI options
Browse files Browse the repository at this point in the history
  • Loading branch information
ayeaye committed Apr 12, 2021
1 parent 283b4a3 commit 5055a96
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 89 deletions.
31 changes: 31 additions & 0 deletions Config.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,34 @@ export Config =
defaultSort:
key: 'title' # see client/RoomList.coffee for other options
reverse: false

## Whether to show darkmode toggle
showUI_dark: true

## Whether to change rooms on click (instead of needing shift-click) by default
default_quickJoin: false
showUI_quickJoin: true

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

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

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

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

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

## Whether to hide the title / button bar at the top of the room tabset by default
default_hideRoombar: false
showUI_hideRoombar: true
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 @@ -455,57 +456,59 @@ export Room = React.memo ({loading, roomId, onClose, enableMaximize, maximized,
</OverlayTrigger>
<div className="Room">
<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
54 changes: 32 additions & 22 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 @@ -145,7 +146,9 @@ export RoomList = React.memo ({loading, model, extraData, updateTab}) ->

<div className="d-flex flex-column h-100 RoomList">
<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 @@ -179,7 +182,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 @@ -240,22 +243,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 @@ -266,7 +271,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 @@ -360,17 +367,20 @@ 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) ->
e.preventDefault()
e.stopPropagation()
currentRoom = Session.get 'currentRoom'
## Open room with focus in the following cases:
## Open room with focus if we're not currently in this room, and any of the following cases:
## * We're not in any rooms
## * Shift/Ctrl/Meta-click => force open
## * Shift/Ctrl/Meta-click xor quickJoin => force open
## * We clicked on the Switch button (force == true)
if not currentRoom? or e.shiftKey or e.ctrlKey or e.metaKey or force == true
if ((not currentRoom?) or
((e.shiftKey or e.ctrlKey or e.metaKey) ^ getUI('quickJoin')) or
(force == true)) and currentRoom != room._id
openRoom room._id
selectRoom null
## Otherwise, toggle whether this room is selected.
Expand Down
58 changes: 45 additions & 13 deletions client/Settings.coffee
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react'
import {useParams} from 'react-router-dom'
import {Card, Form} from 'react-bootstrap'
import {Card, Form, OverlayTrigger, Tooltip} 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,48 @@ 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, tooltip, init) ->
unless init?
init = ->
Config["default_" + name]
uiVars[name] = new LocalStorageVar name, init, sync: true
uiLabels[name] =
label: label
tooltip: tooltip

addUIVar('quickJoin', 'Quick Join', 'Immediately change rooms on click (shift-click to open the room menu)')
addUIVar('dark', 'Dark Mode', 'Light text on dark background', -> window.matchMedia('(prefers-color-scheme: dark)').matches)
addUIVar('compact', 'Compact Mode', 'Condense the list in the "Meeting Rooms" sidebar')
addUIVar('hideCreate', 'Hide Create', 'Hide "Create Room" widget in the "Meeting Rooms" sidebar')
addUIVar('hideSearch', 'Hide Search', 'Hide "Room Search" widget in the "Meeting Rooms" sidebar')
addUIVar('hideStarred', 'Hide Starred', 'Hide "Your Starred Rooms" accordion in the "Meeting Rooms" sidebar')
addUIVar('hideTitle', 'Hide Title', 'Hide meeting title in the "Meeting Rooms" sidebar')
addUIVar('hideRoombar', 'Hide Menubar', 'Hide menubar in room tabset')

export UIToggles = React.memo ->
for name, label of uiLabels
if Config["showUI_" + name]
<UIToggle name={name} key={name}/>
UIToggles.displayName = 'UIToggles'

export UIToggle = React.memo ({name}) ->
value = useUI(name)
label = uiLabels[name]?.label
tooltip = uiLabels[name]?.tooltip
<OverlayTrigger placement="right" overlay={(props) ->
<Tooltip {...props}>{tooltip}</Tooltip>
}>
<div>
<Form.Switch id={name} label={label} checked={value}
onChange={(e) -> uiVars[name].set e.target.checked}/>
</div>
</OverlayTrigger>
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
Loading

0 comments on commit 5055a96

Please sign in to comment.