, space: Space | null) => void
}
-const getFakeSpaceIcon = (space: RoomListFilter | null): JSX.Element | null => {
+const getFakeSpaceMeta = (space: RoomListFilter | null): [string | undefined, JSX.Element | null] => {
switch (space?.id) {
case undefined:
- return
+ return ["Home", ]
case "fi.mau.gomuks.direct_chats":
- return
+ return ["Direct chats", ]
case "fi.mau.gomuks.unreads":
- return
+ return ["Unread chats", ]
case "fi.mau.gomuks.space_orphans":
- return
+ return ["Rooms outside spaces", ]
default:
- return null
+ return [undefined, null]
}
}
const FakeSpace = ({ space, setSpace, isActive, onClickUnread }: FakeSpaceProps) => {
const unreads = useEventAsState(space?.counts)
- const onClickUnreadWrapped = onClickUnread ? () => onClickUnread(null, space) : undefined
- return setSpace(space)}>
+ const onClickUnreadWrapped = onClickUnread
+ ? (evt: React.MouseEvent
) => onClickUnread(evt, space)
+ : undefined
+ const [title, icon] = getFakeSpaceMeta(space)
+ return setSpace(space)} title={title}>
- {getFakeSpaceIcon(space)}
+ {icon}
}
diff --git a/web/src/ui/roomlist/RoomList.css b/web/src/ui/roomlist/RoomList.css
index f7f8e33..0d084d2 100644
--- a/web/src/ui/roomlist/RoomList.css
+++ b/web/src/ui/roomlist/RoomList.css
@@ -119,7 +119,7 @@ div.room-entry {
width: 3rem;
> img.room-avatar {
- padding: 4px;
+ margin: .25rem;
}
}
@@ -172,6 +172,7 @@ div.room-entry-unreads {
justify-content: center;
border-radius: var(--unread-count-size);
color: var(--unread-counter-text-color);
+ user-select: none;
background-color: var(--unread-counter-message-bg);
height: var(--unread-count-size);
diff --git a/web/src/ui/roomlist/RoomList.tsx b/web/src/ui/roomlist/RoomList.tsx
index 04aff8d..c83be1d 100644
--- a/web/src/ui/roomlist/RoomList.tsx
+++ b/web/src/ui/roomlist/RoomList.tsx
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
import React, { use, useCallback, useRef, useState } from "react"
-import { RoomListFilter, Space as SpaceStore, SpaceUnreadCounts } from "@/api/statestore/space.ts"
+import { RoomListFilter, Space as SpaceStore, SpaceUnreadCounts } from "@/api/statestore"
import type { RoomID } from "@/api/types"
import { useEventAsState } from "@/util/eventdispatcher.ts"
import reverseMap from "@/util/reversemap.ts"
@@ -31,41 +31,37 @@ import "./RoomList.css"
interface RoomListProps {
activeRoomID: RoomID | null
+ space: RoomListFilter | null
}
-const RoomList = ({ activeRoomID }: RoomListProps) => {
+const RoomList = ({ activeRoomID, space }: RoomListProps) => {
const client = use(ClientContext)!
const mainScreen = use(MainScreenContext)
const roomList = useEventAsState(client.store.roomList)
const spaces = useEventAsState(client.store.topLevelSpaces)
const searchInputRef = useRef(null)
const [query, directSetQuery] = useState("")
- const [space, directSetSpace] = useState(null)
const setQuery = (evt: React.ChangeEvent) => {
client.store.currentRoomListQuery = toSearchableString(evt.target.value)
directSetQuery(evt.target.value)
}
- const setSpace = useCallback((space: RoomListFilter | null) => {
- directSetSpace(space)
- client.store.currentRoomListFilter = space
- }, [client])
const onClickSpace = useCallback((evt: React.MouseEvent) => {
const store = client.store.getSpaceStore(evt.currentTarget.getAttribute("data-target-space")!)
- setSpace(store)
- }, [setSpace, client])
+ mainScreen.setSpace(store)
+ }, [mainScreen, client])
const onClickSpaceUnread = useCallback((
- evt: React.MouseEvent | null, space?: SpaceStore | null,
+ evt: React.MouseEvent, space?: SpaceStore | null,
) => {
- if (evt) {
+ if (!space) {
const targetSpace = evt.currentTarget.closest("div.space-entry")?.getAttribute("data-target-space")
if (!targetSpace) {
return
}
space = client.store.getSpaceStore(targetSpace)
- }
- if (!space) {
- return
+ if (!space) {
+ return
+ }
}
const counts = space.counts.current
let wantedField: keyof SpaceUnreadCounts
@@ -81,7 +77,8 @@ const RoomList = ({ activeRoomID }: RoomListProps) => {
for (let i = client.store.roomList.current.length - 1; i >= 0; i--) {
const entry = client.store.roomList.current[i]
if (entry[wantedField] > 0 && space.include(entry)) {
- mainScreen.setActiveRoom(entry.room_id)
+ mainScreen.setActiveRoom(entry.room_id, undefined, space)
+ evt.stopPropagation()
break
}
}
@@ -124,11 +121,11 @@ const RoomList = ({ activeRoomID }: RoomListProps) => {
-
+
{client.store.pseudoSpaces.map(pseudoSpace => )}
diff --git a/web/src/ui/roomlist/UnreadCount.tsx b/web/src/ui/roomlist/UnreadCount.tsx
index 82807c0..4ad48f5 100644
--- a/web/src/ui/roomlist/UnreadCount.tsx
+++ b/web/src/ui/roomlist/UnreadCount.tsx
@@ -13,7 +13,7 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-import { SpaceUnreadCounts } from "@/api/statestore/space.ts"
+import { SpaceUnreadCounts } from "@/api/statestore"
interface UnreadCounts extends SpaceUnreadCounts {
marked_unread?: boolean
@@ -38,9 +38,9 @@ const UnreadCount = ({ counts, space, onClick }: UnreadCountProps) => {
const countIsBig = !space
&& Boolean(counts.unread_notifications || counts.unread_highlights || counts.marked_unread)
let unreadCountDisplay = unreadCount.toString()
- if (unreadCount > 999 && countIsBig) {
+ if (unreadCount > 999 && (countIsBig || space)) {
unreadCountDisplay = "99+"
- } else if (unreadCount > 9999 && countIsBig) {
+ } else if (unreadCount > 9999) {
unreadCountDisplay = "999+"
}
const classNames = ["unread-count"]
diff --git a/web/src/ui/settings/SettingsView.tsx b/web/src/ui/settings/SettingsView.tsx
index 6f9aefc..daf5c44 100644
--- a/web/src/ui/settings/SettingsView.tsx
+++ b/web/src/ui/settings/SettingsView.tsx
@@ -237,7 +237,9 @@ const CustomCSSInput = ({ setPref, room }: { setPref: SetPrefFunc, room: RoomSta
}
{vscodeOpen ?
-
}>
+
+ }>
{
)
}
}
+ const onClickOpenCSSApp = () => {
+ client.rpc.requestOpenIDToken().then(
+ resp => window.open(
+ `https://css.gomuks.app/login?token=${resp.access_token}&server_name=${resp.matrix_server_name}`,
+ "_blank",
+ "noreferrer noopener",
+ ),
+ err => window.alert(`Failed to request OpenID token: ${err}`),
+ )
+ }
usePreferences(client.store, room)
const globalServer = client.store.serverPreferenceCache
const globalLocal = client.store.localPreferenceCache
@@ -381,6 +393,7 @@ const SettingsView = ({ room }: SettingsViewProps) => {
+
{window.Notification && }
diff --git a/web/src/ui/timeline/ReadReceipts.css b/web/src/ui/timeline/ReadReceipts.css
index 7e8579d..df23657 100644
--- a/web/src/ui/timeline/ReadReceipts.css
+++ b/web/src/ui/timeline/ReadReceipts.css
@@ -20,6 +20,7 @@ div.timeline-event > div.read-receipts {
> img {
margin-left: -.35rem;
border: 1px solid var(--background-color);
+ background-color: var(--background-color);
}
}