mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2025-12-11 20:15:30 +01:00
Fix tailwind config and add sass dependency
This commit is contained in:
parent
dbd6c61621
commit
792d112d1c
@ -1 +1 @@
|
||||
Subproject commit 85732cc95de98440f9c066042dfbbb809a235936
|
||||
Subproject commit 25bf180122c207661a174b823d2c0f2fa84af550
|
||||
@ -1,10 +1,13 @@
|
||||
import AppKit
|
||||
import SwiftRs
|
||||
|
||||
// Forward declaration of Rust callback
|
||||
// Forward declarations of Rust callbacks
|
||||
@_silgen_name("rust_drag_ended_callback")
|
||||
func rust_drag_ended_callback(_ sessionId: UnsafePointer<CChar>, _ wasDropped: Bool)
|
||||
|
||||
@_silgen_name("rust_drag_moved_callback")
|
||||
func rust_drag_moved_callback(_ sessionId: UnsafePointer<CChar>, _ x: Double, _ y: Double)
|
||||
|
||||
private var activeDragSources: [String: NativeDragSource] = [:]
|
||||
private var dragSourcesLock = NSLock()
|
||||
|
||||
@ -282,15 +285,10 @@ class NativeDragSource: NSObject, NSDraggingSource, NSFilePromiseProviderDelegat
|
||||
)
|
||||
overlay.setFrameOrigin(centeredPoint)
|
||||
|
||||
NotificationCenter.default.post(
|
||||
name: Notification.Name("spacedrive.drag.moved"),
|
||||
object: nil,
|
||||
userInfo: [
|
||||
"sessionId": sessionId,
|
||||
"x": screenPoint.x,
|
||||
"y": screenPoint.y
|
||||
]
|
||||
)
|
||||
// Call Rust callback to emit drag:moved event
|
||||
sessionId.withCString { cString in
|
||||
rust_drag_moved_callback(cString, screenPoint.x, screenPoint.y)
|
||||
}
|
||||
}
|
||||
|
||||
func draggingSession(
|
||||
|
||||
@ -41,8 +41,9 @@ swift!(pub fn begin_native_drag(
|
||||
swift!(pub fn end_native_drag(session_id: &SRString));
|
||||
swift!(pub fn update_drag_overlay_position(session_id: &SRString, x: f64, y: f64));
|
||||
|
||||
// Callback from Swift when drag session ends
|
||||
// Callbacks from Swift
|
||||
static mut DRAG_ENDED_CALLBACK: Option<Box<dyn Fn(&str, bool) + Send + Sync>> = None;
|
||||
static mut DRAG_MOVED_CALLBACK: Option<Box<dyn Fn(&str, f64, f64) + Send + Sync>> = None;
|
||||
|
||||
pub fn set_drag_ended_callback<F>(callback: F)
|
||||
where
|
||||
@ -53,6 +54,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_drag_moved_callback<F>(callback: F)
|
||||
where
|
||||
F: Fn(&str, f64, f64) + Send + Sync + 'static,
|
||||
{
|
||||
unsafe {
|
||||
DRAG_MOVED_CALLBACK = Some(Box::new(callback));
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_drag_ended_callback(session_id: *const std::ffi::c_char, was_dropped: Bool) {
|
||||
let session_id_str = unsafe {
|
||||
@ -68,3 +78,19 @@ pub extern "C" fn rust_drag_ended_callback(session_id: *const std::ffi::c_char,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_drag_moved_callback(session_id: *const std::ffi::c_char, x: f64, y: f64) {
|
||||
let session_id_str = unsafe {
|
||||
std::ffi::CStr::from_ptr(session_id)
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let callback_ptr = &raw const DRAG_MOVED_CALLBACK;
|
||||
if let Some(callback) = (*callback_ptr).as_ref() {
|
||||
callback(&session_id_str, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1246,8 +1246,19 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Setup drag ended callback
|
||||
// Setup drag callbacks
|
||||
let app_handle = app.handle().clone();
|
||||
|
||||
// Drag moved callback
|
||||
let app_for_moved = app_handle.clone();
|
||||
sd_desktop_macos::set_drag_moved_callback(
|
||||
move |_session_id: &str, x: f64, y: f64| {
|
||||
let coordinator = app_for_moved.state::<drag::DragCoordinator>();
|
||||
coordinator.update_position(&app_for_moved, x, y);
|
||||
}
|
||||
);
|
||||
|
||||
// Drag ended callback
|
||||
sd_desktop_macos::set_drag_ended_callback(
|
||||
move |session_id: &str, was_dropped: bool| {
|
||||
tracing::info!(
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
# @jamiepine/assets
|
||||
# @spacedriveapp/assets
|
||||
|
||||
Shared assets for Spacedrive applications.
|
||||
|
||||
@ -1,9 +1,28 @@
|
||||
{
|
||||
"name": "@sd/assets",
|
||||
"version": "1.0.0",
|
||||
"name": "@spacedriveapp/assets",
|
||||
"version": "1.0.1",
|
||||
"license": "GPL-3.0-only",
|
||||
"private": true,
|
||||
"sideEffects": false,
|
||||
"description": "Shared assets for Spacedrive applications",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spacedriveapp/spacedrive.git",
|
||||
"directory": "packages/assets"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"icons",
|
||||
"images",
|
||||
"lottie",
|
||||
"svgs",
|
||||
"util",
|
||||
"videos"
|
||||
],
|
||||
"exports": {
|
||||
"./*": "./*"
|
||||
},
|
||||
"scripts": {
|
||||
"gen": "node ./scripts/generate.mjs"
|
||||
},
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
import { CaretRight } from '@phosphor-icons/react';
|
||||
import clsx from 'clsx';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import type {
|
||||
SpaceGroup as SpaceGroupType,
|
||||
SpaceItem as SpaceItemType,
|
||||
} from '@sd/ts-client';
|
||||
import { useSidebarStore, useLibraryMutation } from '@sd/ts-client';
|
||||
import { useSidebarStore } from '@sd/ts-client';
|
||||
import { SpaceItem } from './SpaceItem';
|
||||
import { DeviceGroup } from './DeviceGroup';
|
||||
import { DevicesGroup } from './DevicesGroup';
|
||||
import { LocationsGroup } from './LocationsGroup';
|
||||
import { VolumesGroup } from './VolumesGroup';
|
||||
import { TagsGroup } from './TagsGroup';
|
||||
import { getDragData, clearDragData, subscribeToDragState } from './dnd';
|
||||
import { usePlatform } from '../../platform';
|
||||
import { subscribeToDragState } from './dnd';
|
||||
|
||||
interface SpaceGroupProps {
|
||||
group: SpaceGroupType;
|
||||
@ -23,15 +22,11 @@ interface SpaceGroupProps {
|
||||
|
||||
export function SpaceGroup({ group, items, spaceId }: SpaceGroupProps) {
|
||||
const { collapsedGroups, toggleGroup } = useSidebarStore();
|
||||
const platform = usePlatform();
|
||||
// Use backend's is_collapsed value as the source of truth, fallback to local state
|
||||
const isCollapsed = group.is_collapsed ?? collapsedGroups.has(group.id);
|
||||
|
||||
// Drag-drop state for custom groups
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [isHovering, setIsHovering] = useState(false);
|
||||
const addItem = useLibraryMutation("spaces.add_item");
|
||||
const groupRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Only QuickAccess and Custom groups can accept drops
|
||||
const canAcceptDrop = group.group_type === 'QuickAccess' || group.group_type === 'Custom';
|
||||
@ -42,51 +37,7 @@ export function SpaceGroup({ group, items, spaceId }: SpaceGroupProps) {
|
||||
return subscribeToDragState(setIsDragging);
|
||||
}, [canAcceptDrop]);
|
||||
|
||||
// Listen for native drag events to track position and handle drop
|
||||
useEffect(() => {
|
||||
if (!platform.onDragEvent || !canAcceptDrop) return;
|
||||
|
||||
const unlisteners: Array<() => void> = [];
|
||||
|
||||
// Track drag position to detect when over this group
|
||||
platform.onDragEvent("moved", (payload: { x: number; y: number }) => {
|
||||
if (!groupRef.current) return;
|
||||
|
||||
const rect = groupRef.current.getBoundingClientRect();
|
||||
const isOver = (
|
||||
payload.x >= rect.left &&
|
||||
payload.x <= rect.right &&
|
||||
payload.y >= rect.top &&
|
||||
payload.y <= rect.bottom
|
||||
);
|
||||
setIsHovering(isOver);
|
||||
}).then(fn => unlisteners.push(fn));
|
||||
|
||||
// Handle drag end - check if dropped on this group
|
||||
platform.onDragEvent("ended", async (payload: { result?: { type: string } }) => {
|
||||
if (payload.result?.type === "Dropped" && isHovering && spaceId) {
|
||||
const dragData = getDragData();
|
||||
if (dragData) {
|
||||
try {
|
||||
await addItem.mutateAsync({
|
||||
space_id: spaceId,
|
||||
group_id: group.id,
|
||||
item_type: { Path: { sd_path: dragData.sdPath } },
|
||||
});
|
||||
console.log("[SpaceGroup] Added item to group:", group.name);
|
||||
} catch (err) {
|
||||
console.error("Failed to add item to group:", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
setIsDragging(false);
|
||||
setIsHovering(false);
|
||||
}).then(fn => unlisteners.push(fn));
|
||||
|
||||
return () => {
|
||||
unlisteners.forEach(fn => fn());
|
||||
};
|
||||
}, [platform, canAcceptDrop, spaceId, group.id, group.name, addItem, isHovering]);
|
||||
// TODO: Drop handling for groups - need to coordinate with parent to avoid duplicates
|
||||
|
||||
// Device groups are special - they show device info with children
|
||||
if (typeof group.group_type === 'object' && 'Device' in group.group_type) {
|
||||
@ -123,11 +74,9 @@ export function SpaceGroup({ group, items, spaceId }: SpaceGroupProps) {
|
||||
// QuickAccess and Custom groups render stored items
|
||||
return (
|
||||
<div
|
||||
ref={groupRef}
|
||||
className={clsx(
|
||||
"rounded-lg transition-colors",
|
||||
isDragging && canAcceptDrop && "bg-accent/10 ring-2 ring-accent/50 ring-inset",
|
||||
isDragging && isHovering && canAcceptDrop && "bg-accent/20 ring-accent"
|
||||
"rounded-lg transition-colors"
|
||||
// TODO: Add drop zone styling when group-level drops are implemented
|
||||
)}
|
||||
>
|
||||
{/* Group Header */}
|
||||
@ -149,15 +98,6 @@ export function SpaceGroup({ group, items, spaceId }: SpaceGroupProps) {
|
||||
{items.map((item) => (
|
||||
<SpaceItem key={item.id} item={item} />
|
||||
))}
|
||||
{/* Drop hint */}
|
||||
{isDragging && canAcceptDrop && (
|
||||
<div className={clsx(
|
||||
"flex items-center justify-center py-2 text-xs font-medium transition-colors",
|
||||
isHovering ? "text-accent" : "text-accent/70"
|
||||
)}>
|
||||
{isHovering ? "Release to add" : "Drop here"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -81,16 +81,19 @@ export function SpacesSidebar({ isPreviewActive = false }: SpacesSidebarProps) {
|
||||
|
||||
// Subscribe to drag state changes (from setDragData)
|
||||
useEffect(() => {
|
||||
return subscribeToDragState(setIsDragging);
|
||||
return subscribeToDragState((dragging) => {
|
||||
console.log("[Sidebar] Drag state changed:", dragging);
|
||||
setIsDragging(dragging);
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Listen for native drag events to track position and handle drop
|
||||
// Listen for drag events to track position and handle drop
|
||||
useEffect(() => {
|
||||
if (!platform.onDragEvent) return;
|
||||
|
||||
const unlisteners: Array<() => void> = [];
|
||||
|
||||
// Track drag position to detect when over sidebar
|
||||
// Track cursor position during drag to detect hover
|
||||
platform.onDragEvent("moved", (payload: { x: number; y: number }) => {
|
||||
if (!dropZoneRef.current) return;
|
||||
|
||||
@ -101,18 +104,28 @@ export function SpacesSidebar({ isPreviewActive = false }: SpacesSidebarProps) {
|
||||
payload.y >= rect.top &&
|
||||
payload.y <= rect.bottom
|
||||
);
|
||||
setIsHovering(isOver);
|
||||
|
||||
if (isOver !== isHovering) {
|
||||
console.log("[Sidebar] Hover state changed:", isOver);
|
||||
setIsHovering(isOver);
|
||||
}
|
||||
}).then(fn => unlisteners.push(fn));
|
||||
|
||||
// Handle drag end - check if dropped on sidebar
|
||||
platform.onDragEvent("ended", async (payload: { result?: { type: string } }) => {
|
||||
const dragData = getDragData(); // Get BEFORE clearing
|
||||
console.log("[Sidebar] drag:ended", {
|
||||
wasDropped: payload.result?.type?.toLowerCase() === "dropped",
|
||||
isHovering,
|
||||
hasSpace: !!currentSpace,
|
||||
hasDragData: !!dragData
|
||||
});
|
||||
|
||||
// Check for "dropped" (lowercase from backend)
|
||||
const wasDropped = payload.result?.type?.toLowerCase() === "dropped";
|
||||
|
||||
// If dropped and we have drag data from our app, add it to the space
|
||||
if (wasDropped && currentSpace && dragData) {
|
||||
// Only add if dropped AND hovering over the sidebar
|
||||
if (wasDropped && isHovering && currentSpace && dragData) {
|
||||
try {
|
||||
await addItem.mutateAsync({
|
||||
space_id: currentSpace.id,
|
||||
@ -155,8 +168,7 @@ export function SpacesSidebar({ isPreviewActive = false }: SpacesSidebarProps) {
|
||||
ref={dropZoneRef}
|
||||
className={clsx(
|
||||
"no-scrollbar mt-3 mask-fade-out flex grow flex-col space-y-5 overflow-x-hidden overflow-y-scroll pb-10 transition-colors rounded-lg",
|
||||
isDragging && "bg-accent/10 ring-2 ring-accent/50 ring-inset",
|
||||
isDragging && isHovering && "bg-accent/20 ring-accent"
|
||||
isDragging && isHovering && "bg-accent/10 ring-2 ring-accent/50 ring-inset"
|
||||
)}
|
||||
>
|
||||
{/* Space-level items (pinned shortcuts) */}
|
||||
|
||||
@ -1,16 +1,26 @@
|
||||
{
|
||||
"name": "@sd/ui",
|
||||
"version": "0.0.0",
|
||||
"name": "@spacedriveapp/ui",
|
||||
"version": "1.0.2",
|
||||
"license": "GPL-3.0-only",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"description": "React component library for Spacedrive applications",
|
||||
"main": "dist/index.mjs",
|
||||
"module": "dist/index.mjs",
|
||||
"sideEffects": [
|
||||
"./style/index.js",
|
||||
"./style/style.scss"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spacedriveapp/spacedrive.git",
|
||||
"directory": "packages/ui"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./src/forms": "./src/forms/index.ts",
|
||||
".": "./dist/index.mjs",
|
||||
"./forms": "./dist/forms/index.mjs",
|
||||
"./src/forms": "./dist/forms/index.mjs",
|
||||
"./postcss": "./style/postcss.config.js",
|
||||
"./tailwind": "./style/tailwind.js",
|
||||
"./style": "./style/index.js",
|
||||
@ -19,10 +29,12 @@
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"style"
|
||||
"style",
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"prepublishOnly": "bun run build",
|
||||
"lint": "eslint src --cache",
|
||||
"typecheck": "tsc -b"
|
||||
},
|
||||
@ -44,7 +56,7 @@
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.0.7",
|
||||
"@react-spring/web": "9.7.3",
|
||||
"@sd/assets": "workspace:*",
|
||||
"@spacedriveapp/assets": "^1.0.1",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"@zxcvbn-ts/language-common": "^3.0.4",
|
||||
"@zxcvbn-ts/language-en": "^3.0.2",
|
||||
|
||||
@ -9,7 +9,7 @@ export default defineConfig({
|
||||
'react',
|
||||
'react-dom',
|
||||
'react-router-dom',
|
||||
'@jamiepine/assets',
|
||||
'@spacedriveapp/assets',
|
||||
'zod',
|
||||
'clsx',
|
||||
'class-variance-authority',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user