mirror of
https://github.com/luminous-devs/lume.git
synced 2024-10-01 01:10:48 +00:00
feat: add ability change column name on the fly (#180)
Co-authored-by: reya <reya@lume.nu>
This commit is contained in:
parent
17766d29d6
commit
c755b8d137
@ -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>
|
||||||
|
@ -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", () => {
|
||||||
|
3
packages/types/index.d.ts
vendored
3
packages/types/index.d.ts
vendored
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
<div className="relative flex gap-2 items-center">
|
||||||
{!children ? (
|
{!children ? (
|
||||||
<div className="text-[13px] font-medium">{name}</div>
|
<div
|
||||||
|
contentEditable
|
||||||
|
suppressContentEditableWarning={true}
|
||||||
|
onBlur={(e) => setTitle(e.currentTarget.textContent)}
|
||||||
|
className="text-[13px] font-medium focus:outline-none"
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
children
|
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"
|
||||||
|
Loading…
Reference in New Issue
Block a user