feat: add ability change column name on the fly (#180)

Co-authored-by: reya <reya@lume.nu>
This commit is contained in:
Ren Amamiya 2024-04-22 14:33:14 +07:00 committed by GitHub
parent 17766d29d6
commit c755b8d137
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 70 additions and 9 deletions

View File

@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from "react";
import { LumeColumn } from "@lume/types"; import { LumeColumn } from "@lume/types";
import { invoke } from "@tauri-apps/api/core"; import { invoke } from "@tauri-apps/api/core";
import { Spinner } from "@lume/ui"; import { Spinner } from "@lume/ui";
import { cn } from "@lume/utils";
export function Col({ export function Col({
column, column,
@ -83,7 +84,12 @@ export function Col({
return ( return (
<div ref={container} className="h-full w-[440px] shrink-0 p-2"> <div ref={container} className="h-full w-[440px] shrink-0 p-2">
{column.label !== "open" ? ( {column.label !== "open" ? (
<div className="w-full h-full flex items-center justify-center rounded-xl flex-col bg-black/5 dark:bg-white/5 backdrop-blur-lg"> <div
className={cn(
"w-full h-full flex items-center justify-center rounded-xl flex-col",
!webview ? "bg-black/5 dark:bg-white/5 backdrop-blur-lg" : "",
)}
>
<button type="button" className="size-5" disabled> <button type="button" className="size-5" disabled>
<Spinner className="size-5" /> <Spinner className="size-5" />
</button> </button>

View File

@ -89,6 +89,18 @@ function Screen() {
}); });
}, 150); }, 150);
const updateName = useDebouncedCallback((label: string, title: string) => {
const currentColIndex = columns.findIndex((col) => col.label === label);
const updatedCol = Object.assign({}, columns[currentColIndex]);
updatedCol.name = title;
const newCols = columns.slice();
newCols[currentColIndex] = updatedCol;
setColumns(newCols);
}, 150);
const startResize = useDebouncedCallback( const startResize = useDebouncedCallback(
() => setIsResize((prev) => !prev), () => setIsResize((prev) => !prev),
150, 150,
@ -111,6 +123,8 @@ function Screen() {
unlistenColEvent = await listen<EventColumns>("columns", (data) => { unlistenColEvent = await listen<EventColumns>("columns", (data) => {
if (data.payload.type === "add") add(data.payload.column); if (data.payload.type === "add") add(data.payload.column);
if (data.payload.type === "remove") remove(data.payload.label); if (data.payload.type === "remove") remove(data.payload.label);
if (data.payload.type === "set_title")
updateName(data.payload.label, data.payload.title);
}); });
unlistenWindowResize = await getCurrent().listen("tauri://resize", () => { unlistenWindowResize = await getCurrent().listen("tauri://resize", () => {

View File

@ -102,8 +102,9 @@ export interface LumeColumn {
} }
export interface EventColumns { export interface EventColumns {
type: "add" | "remove" | "update" | "left" | "right"; type: "add" | "remove" | "update" | "left" | "right" | "set_title";
label?: string; label?: string;
title?: string;
column?: LumeColumn; column?: LumeColumn;
} }

View File

@ -1,7 +1,8 @@
import { CancelIcon, ExpandIcon, RefreshIcon } from "@lume/icons"; import { CancelIcon, CheckIcon, RefreshIcon } from "@lume/icons";
import { cn } from "@lume/utils"; import { cn } from "@lume/utils";
import { useSearch } from "@tanstack/react-router";
import { getCurrent } from "@tauri-apps/api/window"; import { getCurrent } from "@tauri-apps/api/window";
import { ReactNode } from "react"; import { ReactNode, useEffect, useState } from "react";
export function ColumnHeader({ export function ColumnHeader({
label, label,
@ -14,6 +15,23 @@ export function ColumnHeader({
className?: string; className?: string;
children?: ReactNode; children?: ReactNode;
}) { }) {
const search = useSearch({ strict: false });
const [title, setTitle] = useState(name);
const [isChanged, setIsChanged] = useState(false);
const saveNewTitle = async () => {
const mainWindow = getCurrent();
await mainWindow.emit("columns", { type: "set_title", label, title });
// update search params
// @ts-ignore, hahaha
search.name = title;
// reset state
setIsChanged(false);
};
const reload = () => { const reload = () => {
window.location.reload(); window.location.reload();
}; };
@ -23,6 +41,10 @@ export function ColumnHeader({
await mainWindow.emit("columns", { type: "remove", label }); await mainWindow.emit("columns", { type: "remove", label });
}; };
useEffect(() => {
if (title.length !== name.length) setIsChanged(true);
}, [title]);
return ( return (
<div <div
className={cn( className={cn(
@ -30,11 +52,29 @@ export function ColumnHeader({
className, className,
)} )}
> >
{!children ? ( <div className="relative flex gap-2 items-center">
<div className="text-[13px] font-medium">{name}</div> {!children ? (
) : ( <div
children contentEditable
)} suppressContentEditableWarning={true}
onBlur={(e) => setTitle(e.currentTarget.textContent)}
className="text-[13px] font-medium focus:outline-none"
>
{name}
</div>
) : (
children
)}
{isChanged ? (
<button
type="button"
onClick={saveNewTitle}
className="text-teal-500 hover:text-teal-600"
>
<CheckIcon className="size-4" />
</button>
) : null}
</div>
<div className="inline-flex items-center gap-1"> <div className="inline-flex items-center gap-1">
<button <button
type="button" type="button"