Skip to content

Commit

Permalink
add tab left right hotkeys
Browse files Browse the repository at this point in the history
  • Loading branch information
natew committed Dec 11, 2024
1 parent 3759d93 commit b8aa0c7
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 222 deletions.
2 changes: 1 addition & 1 deletion apps/onechat/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useState } from 'react'
import { TamaguiProvider, YStack } from 'tamagui'
import config from '~/config/tamagui/tamagui.config'
import { AuthEffects } from '~/features/auth/AuthEffects'
import { useZeroInstanceEmitter, zero } from '~/features/zero/zero'
import { useZeroInstanceEmitter, zero } from '~/features/state/zero'

export default function Layout() {
return (
Expand Down
15 changes: 10 additions & 5 deletions apps/onechat/app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MessageCircle, UserCircle } from '@tamagui/lucide-icons'
import { memo, useRef, useState } from 'react'
import { memo, useEffect, useRef, useState } from 'react'
import {
Button,
Circle,
Expand All @@ -18,12 +18,12 @@ import type { Message, User } from '~/config/zero/schema'
import { authClient } from '~/features/auth/authClient'
import { githubSignIn } from '~/features/auth/githubSignIn'
import { useAuth } from '~/features/auth/useAuth'
import { useUserState } from '~/features/auth/useUserState'
import { useUserState } from '~/features/state/useUserState'
import { OneBall } from '~/features/brand/Logo'
import { isTauri } from '~/features/tauri/constants'
import { randomID } from '~/features/zero/randomID'
import { useCurrentChannel, useCurrentMessages, useCurrentServer } from '~/features/zero/useServer'
import { mutate } from '~/features/zero/zero'
import { randomID } from '~/features/state/randomID'
import { useCurrentChannel, useCurrentMessages, useCurrentServer } from '~/features/state/useServer'
import { mutate } from '~/features/state/zero'
import { Avatar } from '~/interface/Avatar'
import { ListItem } from '~/interface/ListItem'
import { Sidebar } from '~/interface/Sidebar'
Expand Down Expand Up @@ -287,6 +287,11 @@ const MessageArea = () => {
const { user } = useAuth()
const disabled = !user

// on channel change, focus input
useEffect(() => {
inputRef.current?.focus()
}, [channel])

return (
<YStack btw={1} bc="$color4" p="$2">
<Input
Expand Down
2 changes: 1 addition & 1 deletion apps/onechat/features/auth/AuthEffects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { onOpenUrl } from '@tauri-apps/plugin-deep-link'
import { useEffect } from 'react'
import { setAuthToken } from './authClient'
import { useAuth } from './useAuth'
import { setZeroAuth } from '../zero/zero'
import { setZeroAuth } from '../state/zero'

export const AuthEffects = () => {
useAuthPassTokenToTauriEffect()
Expand Down
2 changes: 1 addition & 1 deletion apps/onechat/features/hotmenu/HotMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Slash } from '@tamagui/lucide-icons'
import { useHotkeys } from 'react-hotkeys-hook'
import { Button } from '~/interface/Button'
import { updateUserState, useUserState } from '../auth/useUserState'
import { updateUserState, useUserState } from '../state/useUserState'
import { Dialog, Input, type TamaguiElement } from 'tamagui'
import { forwardRef } from 'react'

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useUserState } from '../auth/useUserState'
import { useUserState } from './useUserState'
import { useQuery } from './zero'

export const useServersQuery = () => useQuery((q) => q.server)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { User } from '~/config/zero/schema'
import { mutate, useQuery } from '~/features/zero/zero'
import { mutate, useQuery } from '~/features/state/zero'

// were using JSONB for UserState
type UserState = {
Expand Down
File renamed without changes.
209 changes: 3 additions & 206 deletions apps/onechat/interface/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,7 @@
import {
closestCenter,
DndContext,
DragOverlay,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
} from '@dnd-kit/core'
import {
SortableContext,
sortableKeyboardCoordinates,
useSortable,
verticalListSortingStrategy,
} from '@dnd-kit/sortable'
import { Menu } from '@tauri-apps/api/menu'
import { forwardRef, memo, useEffect, useState } from 'react'
import { H3, SizableText, Spacer, XStack, type XStackProps, YStack } from 'tamagui'
import type { Channel } from '~/config/zero/schema'
import { updateUserState, useUserState } from '~/features/auth/useUserState'
import { randomID } from '~/features/zero/randomID'
import { useCurrentServer, useServerChannels } from '~/features/zero/useServer'
import { mutate } from '~/features/zero/zero'
import { ListItem } from './ListItem'
import { memo } from 'react'
import { H3, SizableText, Spacer, XStack, YStack } from 'tamagui'
import { SidebarServersRow } from './SidebarServersRow'
import { SidebarServerChannelsList } from './SidebarServerChannelsList'

export const Sidebar = memo(() => {
return (
Expand Down Expand Up @@ -53,188 +32,6 @@ export const Sidebar = memo(() => {
)
})

const SidebarServerChannelsList = () => {
const server = useCurrentServer()
const channels = useServerChannels() || []
const sensors = useSensors(
useSensor(PointerSensor, {
activationConstraint: {
delay: 100,
distance: {
y: 8,
},
},
}),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
})
)
const [{ activeServer, activeChannels }] = useUserState()

// ensure theres always a selected channel
useEffect(() => {
if (!server) return
if (!activeServer) return
if (!channels[0]) return
if (activeChannels[server.id]) return
updateUserState({
activeChannels: {
...activeChannels,
[server.id]: channels[0].id,
},
})
}, [channels, server, activeServer])

function handleDragEnd(event) {
setDragging(null)

const { active, over } = event

if (active.id !== over.id) {
// setItems((items) => {
// const oldIndex = items.indexOf(active.id);
// const newIndex = items.indexOf(over.id);
// return arrayMove(items, oldIndex, newIndex);
// });
}
}

const [dragging, setDragging] = useState(null)

function handleDragStart(event) {
const { active } = event
setDragging(active)
}

return (
<YStack>
<YStack pos="relative">
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
>
<SortableContext items={channels} strategy={verticalListSortingStrategy}>
{channels.map((channel) => {
return <ChannelListItemSortable key={channel.id} channel={channel} />
})}
<DragOverlay
style={{
zIndex: 1000,
}}
>
{dragging ? <DraggedChannel channel={dragging} /> : null}
</DragOverlay>
</SortableContext>
</DndContext>
</YStack>

<ListItem
onPress={() => {
if (!server) {
alert('no server')
return
}

mutate.channel.insert({
id: randomID(),
createdAt: new Date().getTime(),
description: '',
name: 'Hello',
private: false,
serverId: server.id,
})
}}
>
Create Channel
</ListItem>
</YStack>
)
}

const DraggedChannel = ({ channel }: { channel: Channel }) => {
return <ChannelListItem channel={channel} />
}

const ChannelListItemSortable = ({ channel }: { channel: Channel }) => {
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
id: channel.id,
})

return (
<ChannelListItem
ref={setNodeRef}
{...attributes}
{...listeners}
{...transform}
channel={channel}
transition={transition}
// @ts-expect-error
onContextMenu={async (e) => {
e.preventDefault()
const menu = Menu.new({
items: [
{
id: 'ctx_option1',
text: 'Delete',
action() {
mutate.channel.delete({
id: channel.id,
})
},
},
],
})
const menuInstance = await menu
menuInstance.popup()
}}
>
{channel.name}
</ChannelListItem>
)
}

const ChannelListItem = forwardRef(
({ channel, ...rest }: XStackProps & { channel: Channel }, ref: any) => {
const [editing, setEditing] = useState(false)
const [userState, derivedUserState] = useUserState()

return (
<ListItem
ref={ref}
editing={editing}
active={derivedUserState?.activeChannel === channel.id}
onPress={() => {
updateUserState({
activeChannels: {
...userState.activeChannels,
[userState.activeServer!]: channel.id,
},
})
}}
onEditCancel={() => {
setEditing(false)
}}
onEditComplete={(next) => {
setEditing(false)
mutate.channel.update({
...channel,
name: next,
})
}}
// @ts-expect-error
onDoubleClick={() => {
setEditing(!editing)
}}
{...rest}
>
{channel.name}
</ListItem>
)
}
)

const SubTitle = (props) => {
return (
<H3 cur="default" userSelect="none" px="$2.5" py="$1.5" o={0.4} size="$2">
Expand Down
Loading

0 comments on commit b8aa0c7

Please sign in to comment.