Skip to content

Commit

Permalink
feat: add recent connection
Browse files Browse the repository at this point in the history
  • Loading branch information
invisal committed Sep 28, 2023
1 parent c6b840d commit b911e25
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 236 deletions.
9 changes: 7 additions & 2 deletions src/libs/ConnectionListStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,20 @@ export default class ConnectionListStorage {
return this.connections;
}

async save(data: Omit<ConnectionStoreItem, 'id'> & { id?: string }) {
async save(
data: Omit<ConnectionStoreItem, 'id'> & { id?: string },
): Promise<ConnectionStoreItem> {
const id = data.id ? data.id : uuidv1();
const newData: ConnectionStoreItem = {
...data,
id: data.id ? data.id : uuidv1(),
id,
createdAt: data.createdAt ? data.createdAt : Math.ceil(Date.now() / 1000),
};

this.dict[newData.id] = newData;
db.table('connections').put(newData);

return newData;
}

async remove(id: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import useNewConnectionMenu from './useNewConnectionMenu';

export default function ConnectionToolbar() {
const menu = useNewConnectionMenu();

return (
<Toolbar>
<Toolbar.ContextMenu
icon={<FontAwesomeIcon icon={faAdd} />}
text=""
icon={<FontAwesomeIcon icon={faAdd} color="#2980b9" />}
text="New Connection"
items={menu}
/>
</Toolbar>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ export default function EditConnectionModal({
}: {
initialValue: ConnectionStoreItemWithoutId;
}) {
const { finishEditing, refresh, storage } = useConnectionList();
const { finishEditing, refresh, storage, setSelectedItem } =
useConnectionList();
const [value, setValue] = useState(initialValue);

const onSave = useCallback(() => {
storage
.save(value)
.then(() => {
.then((newItem) => {
refresh();
finishEditing();
setSelectedItem({ id: newItem.id, data: newItem });
})
.catch(console.error);
}, [finishEditing, value]);
Expand Down
85 changes: 62 additions & 23 deletions src/renderer/components/ConnectionListTree/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ const ConnectionListContext = createContext<{
refresh: () => void;
finishEditing: () => void;
showEditConnection: (initialValue: ConnectionStoreItemWithoutId) => void;
setSelectedItem: React.Dispatch<
React.SetStateAction<TreeViewItemData<ConnectionStoreItem> | undefined>
>;
}>({
storage: new ConnectionListStorage(),
refresh: NotImplementCallback,
finishEditing: NotImplementCallback,
showEditConnection: NotImplementCallback,
setSelectedItem: NotImplementCallback,
});

export function useConnectionList() {
Expand All @@ -39,34 +43,59 @@ export function useConnectionList() {

function ConnectionListTreeBody({
connectionList,
selectedItem,
setSelectedItem,
}: {
connectionList: ConnectionStoreItem[];
selectedItem: TreeViewItemData<ConnectionStoreItem> | undefined;
setSelectedItem: React.Dispatch<
React.SetStateAction<TreeViewItemData<ConnectionStoreItem> | undefined>
>;
}) {
const [collapsed, setCollapsed] = useState<string[] | undefined>(['recent']);
const { connect } = useConnection();
const [selectedItem, setSelectedItem] =
useState<TreeViewItemData<ConnectionStoreItem>>();
const { storage, refresh } = useConnectionList();

const treeItemList: TreeViewItemData<ConnectionStoreItem>[] = useMemo(() => {
return connectionList.map(
(connection): TreeViewItemData<ConnectionStoreItem> => {
return {
id: connection.id,
data: connection,
icon: <ConnectionIcon dialect={connection.type} />,
text: connection.name,
};
const tmp = [...connectionList];
tmp.sort((a, b) => b.lastUsedAt - a.lastUsedAt);
const recentConnections = tmp.slice(0, 5);
const recentIds = recentConnections.map((r) => r.id);

const other = connectionList.filter((c) => !recentIds.includes(c.id));

return [
{
id: 'recent',
text: 'Recent',
children: recentConnections.map(
(connection): TreeViewItemData<ConnectionStoreItem> => {
return {
id: connection.id,
data: connection,
icon: <ConnectionIcon dialect={connection.type} />,
text: connection.name,
};
},
),
},
{
id: 'other',
text: 'Other',
children: other.map(
(connection): TreeViewItemData<ConnectionStoreItem> => {
return {
id: connection.id,
data: connection,
icon: <ConnectionIcon dialect={connection.type} />,
text: connection.name,
};
},
),
},
);
].filter((r) => r.children.length > 0);
}, [connectionList]);

useEffect(() => {
if (selectedItem && treeItemList) {
if (!treeItemList.map((t) => t.id).includes(selectedItem.id)) {
setSelectedItem(undefined);
}
}
}, [treeItemList, selectedItem, setSelectedItem]);

const { handleContextMenu } = useConnectionContextMenu({
selectedItem: selectedItem?.data,
});
Expand All @@ -77,9 +106,13 @@ function ConnectionListTreeBody({
selected={selectedItem}
onContextMenu={handleContextMenu}
onSelectChange={setSelectedItem}
collapsedKeys={collapsed}
onCollapsedChange={setCollapsed}
onDoubleClick={(e) => {
if (e.data) {
connect(e.data);
storage.updateLastUsed(e.data.id);
refresh();
}
}}
emptyState={
Expand All @@ -91,9 +124,10 @@ function ConnectionListTreeBody({

export default function ConnectionListTree() {
const storage = useMemo(() => new ConnectionListStorage(), []);
const [editingItem, setEditingItem] = useState<
ConnectionStoreItemWithoutId | undefined
>();
const [selectedItem, setSelectedItem] =
useState<TreeViewItemData<ConnectionStoreItem>>();
const [editingItem, setEditingItem] =
useState<ConnectionStoreItemWithoutId>();
const [connectionList, setConnectionList] = useState<ConnectionStoreItem[]>(
[],
);
Expand All @@ -118,13 +152,18 @@ export default function ConnectionListTree() {
refresh: onRefresh,
finishEditing: onFinishEditing,
showEditConnection: setEditingItem,
setSelectedItem: setSelectedItem,
}}
>
<Layout>
<Layout.Fixed>
<ConnectionToolbar />
</Layout.Fixed>
<ConnectionListTreeBody connectionList={connectionList} />
<ConnectionListTreeBody
connectionList={connectionList}
selectedItem={selectedItem}
setSelectedItem={setSelectedItem}
/>
</Layout>

{editingItem && <EditConnectionModal initialValue={editingItem} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export default function useConnectionContextMenu({
}: {
selectedItem?: ConnectionStoreItem;
}) {
const { storage, refresh, showEditConnection } = useConnectionList();
const { storage, refresh, showEditConnection, setSelectedItem } =
useConnectionList();
const newConnectionMenu = useNewConnectionMenu();

const onRemoveClick = useCallback(async () => {
Expand All @@ -24,8 +25,9 @@ export default function useConnectionContextMenu({

storage.remove(selectedItem.id);
refresh();
setSelectedItem(undefined);
}
}, [selectedItem, storage]);
}, [selectedItem, storage, setSelectedItem]);

const { handleContextMenu } = useContextMenu(() => {
return [
Expand Down
18 changes: 16 additions & 2 deletions src/renderer/components/Toolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,14 @@ Toolbar.Item = function ({
onClick={disabled ? undefined : onClick}
style={{ opacity: disabled ? 0.5 : 1 }}
>
{icon && <span className={styles.icon}>{icon}</span>}
{icon && (
<span
className={styles.icon}
style={{ marginRight: text ? '8px' : undefined }}
>
{icon}
</span>
)}
{text && <span className={styles.text}>{text}</span>}
{badge ? <span className={styles.badge}>{badge}</span> : <></>}
{keyboard && <KeyboardKey name={keyboard} />}
Expand Down Expand Up @@ -119,7 +126,14 @@ Toolbar.ContextMenu = function ToolbarContextMenu({
const activator = useCallback(() => {
return (
<li className={styles.button}>
{icon && <span className={styles.icon}>{icon}</span>}
{icon && (
<span
className={styles.icon}
style={{ marginRight: text ? '8px' : undefined }}
>
{icon}
</span>
)}
<span>{text}</span>
</li>
);
Expand Down
1 change: 0 additions & 1 deletion src/renderer/components/Toolbar/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

span.icon {
display: inline-block;
margin-right: 8px;
}

span.icon:last-child {
Expand Down
Loading

0 comments on commit b911e25

Please sign in to comment.