mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 12:13:27 +00:00
[macOS] native sidebar blur effect (#239)
* wip rust bindings * wip rust bindings * attempt raw objc for window blur -- still nothing * some minor blurring success... * Fix macOS sidebar blur * darken sidebar * lock to dark theme * remove commented, unused window-blur lines * remove xcode user state * ADD SWIFT WINDOW CODE * refactor: use swift window code * remove stupid cas warning * add webview swift util for reload * remove objc and cocoa * remove old unused swift build fix * simplify swift package fn calls * enumify app theme * fix main content view not expanding * fix sidebar folder item layout * fix swift version requirement * fix landing package json * landing tweaks * sidebar style tweaks for macOS Co-authored-by: maxichrome <maxichrome@users.noreply.github.com> Co-authored-by: Jamie Pine <ijamespine@me.com>
This commit is contained in:
parent
d7c070b7cb
commit
498da6a73e
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -15,6 +15,7 @@
|
|||
"Roadmap",
|
||||
"svgr",
|
||||
"tailwindcss",
|
||||
"titlebar",
|
||||
"trivago",
|
||||
"tsparticles",
|
||||
"unlisten",
|
||||
|
|
2170
Cargo.lock
generated
2170
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -7,11 +7,10 @@ license = ""
|
|||
repository = "https://github.com/spacedriveapp/spacedrive"
|
||||
default-run = "spacedrive"
|
||||
edition = "2021"
|
||||
build = "src/build.rs"
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.0.0-rc.5", features = [] }
|
||||
swift-rs = "0.2.3"
|
||||
|
||||
[dependencies]
|
||||
# Project dependencies
|
||||
|
@ -25,8 +24,10 @@ window-shadows = "0.1.2"
|
|||
|
||||
# macOS system libs
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
cocoa = "0.24.0"
|
||||
objc = "0.2.7"
|
||||
swift-rs = { git = "https://github.com/Brendonovich/swift-rs.git", branch = "autorelease" }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.build-dependencies]
|
||||
swift-rs = { git = "https://github.com/Brendonovich/swift-rs.git", branch = "autorelease", features = ["build"] }
|
||||
|
||||
[features]
|
||||
default = [ "custom-protocol" ]
|
||||
|
|
8
apps/desktop/src-tauri/build.rs
Normal file
8
apps/desktop/src-tauri/build.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use swift_rs::build::{link_swift, link_swift_package};
|
||||
|
||||
fn main() {
|
||||
link_swift();
|
||||
link_swift_package("sd-desktop-macos", "./native/macos/");
|
||||
|
||||
tauri_build::build();
|
||||
}
|
9
apps/desktop/src-tauri/native/macos/.gitignore
vendored
Normal file
9
apps/desktop/src-tauri/native/macos/.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/config/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.netrc
|
16
apps/desktop/src-tauri/native/macos/Package.resolved
Normal file
16
apps/desktop/src-tauri/native/macos/Package.resolved
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"object": {
|
||||
"pins": [
|
||||
{
|
||||
"package": "SwiftRs",
|
||||
"repositoryURL": "https://github.com/brendonovich/swift-rs.git",
|
||||
"state": {
|
||||
"branch": "autorelease",
|
||||
"revision": "fe5a1c2f668e6bade43d6f56e2530f110055cee9",
|
||||
"version": null
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"version": 1
|
||||
}
|
32
apps/desktop/src-tauri/native/macos/Package.swift
Normal file
32
apps/desktop/src-tauri/native/macos/Package.swift
Normal file
|
@ -0,0 +1,32 @@
|
|||
// swift-tools-version: 5.5
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "sd-desktop-macos",
|
||||
platforms: [
|
||||
.macOS(.v11)
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||
.library(
|
||||
name: "sd-desktop-macos",
|
||||
type: .static,
|
||||
targets: ["sd-desktop-macos"]
|
||||
),
|
||||
],
|
||||
dependencies: [
|
||||
// Dependencies declare other packages that this package depends on.
|
||||
.package(url: "https://github.com/brendonovich/swift-rs.git", branch: "autorelease"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||
.target(
|
||||
name: "sd-desktop-macos",
|
||||
dependencies: [
|
||||
.product(name: "SwiftRs", package: "swift-rs")
|
||||
]),
|
||||
]
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
import WebKit
|
||||
|
||||
@_cdecl("reload_webview")
|
||||
public func reloadWebview(webview: WKWebView) -> () {
|
||||
webview.window!.orderOut(webview);
|
||||
webview.reload();
|
||||
webview.window!.makeKey();
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import AppKit
|
||||
|
||||
@objc
|
||||
public enum AppThemeType: Int {
|
||||
case light = 0;
|
||||
case dark = 1;
|
||||
}
|
||||
|
||||
@_cdecl("lock_app_theme")
|
||||
public func lockAppTheme(themeType: AppThemeType) {
|
||||
var theme: NSAppearance;
|
||||
|
||||
switch themeType {
|
||||
case .dark:
|
||||
theme = NSAppearance(named: .darkAqua)!;
|
||||
case .light:
|
||||
theme = NSAppearance(named: .aqua)!;
|
||||
}
|
||||
|
||||
NSApp.appearance = theme;
|
||||
}
|
||||
|
||||
@_cdecl("blur_window_background")
|
||||
public func blurWindowBackground(window: NSWindow) {
|
||||
let windowContent = window.contentView!;
|
||||
let blurryView = NSVisualEffectView();
|
||||
|
||||
blurryView.material = .sidebar;
|
||||
blurryView.state = .followsWindowActiveState;
|
||||
blurryView.blendingMode = .behindWindow;
|
||||
blurryView.wantsLayer = true;
|
||||
|
||||
window.contentView = blurryView;
|
||||
blurryView.addSubview(windowContent);
|
||||
}
|
||||
|
||||
@_cdecl("set_invisible_toolbar")
|
||||
public func setInvisibleToolbar(window: NSWindow, hasToolbar: Bool) {
|
||||
if !hasToolbar {
|
||||
window.toolbar = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
let toolbar = NSToolbar(identifier: "window_invisible_toolbar");
|
||||
|
||||
toolbar.showsBaselineSeparator = false;
|
||||
window.toolbar = toolbar;
|
||||
}
|
||||
|
||||
@_cdecl("set_titlebar_style")
|
||||
public func setTitlebarStyle(window: NSWindow, transparent: Bool, large: Bool) {
|
||||
var styleMask = window.styleMask;
|
||||
|
||||
if transparent && large {
|
||||
styleMask.insert(.unifiedTitleAndToolbar);
|
||||
}
|
||||
|
||||
window.styleMask = styleMask;
|
||||
|
||||
if large {
|
||||
setInvisibleToolbar(window: window, hasToolbar: true);
|
||||
}
|
||||
|
||||
window.titleVisibility = transparent ? .hidden : .visible;
|
||||
window.titlebarAppearsTransparent = transparent;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
// use swift_rs::build_utils::{link_swift, link_swift_package};
|
||||
|
||||
fn main() {
|
||||
// HOTFIX: compile the swift code for arm64
|
||||
// std::env::set_var("CARGO_CFG_TARGET_ARCH", "arm64");
|
||||
|
||||
// link_swift();
|
||||
// link_swift_package("swift-lib", "../../../packages/macos/");
|
||||
|
||||
tauri_build::build();
|
||||
}
|
7
apps/desktop/src-tauri/src/macos/mod.rs
Normal file
7
apps/desktop/src-tauri/src/macos/mod.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
mod native;
|
||||
|
||||
mod window;
|
||||
pub use window::*;
|
||||
|
||||
mod webview;
|
||||
pub use webview::*;
|
3
apps/desktop/src-tauri/src/macos/native.rs
Normal file
3
apps/desktop/src-tauri/src/macos/native.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
use std::ffi::c_void;
|
||||
|
||||
pub type NSObject = *mut c_void;
|
4
apps/desktop/src-tauri/src/macos/webview.rs
Normal file
4
apps/desktop/src-tauri/src/macos/webview.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
use super::native::NSObject;
|
||||
use swift_rs::*;
|
||||
|
||||
pub_swift_fn!(reload_webview(webview: NSObject));
|
17
apps/desktop/src-tauri/src/macos/window.rs
Normal file
17
apps/desktop/src-tauri/src/macos/window.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use super::native::NSObject;
|
||||
use swift_rs::*;
|
||||
|
||||
pub_swift_fn!(lock_app_theme(theme_type: Int));
|
||||
pub_swift_fn!(blur_window_background(window: NSObject));
|
||||
pub_swift_fn!(set_invisible_toolbar(window: NSObject, shown: Bool));
|
||||
pub_swift_fn!(set_titlebar_style(
|
||||
window: NSObject,
|
||||
transparent: Bool,
|
||||
large: Bool
|
||||
));
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum AppThemeType {
|
||||
Light = 0 as Int,
|
||||
Dark = 1 as Int,
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
use std::time::{Duration, Instant};
|
||||
|
||||
use macos::AppThemeType;
|
||||
use sdcore::{ClientCommand, ClientQuery, CoreController, CoreEvent, CoreResponse, Node};
|
||||
use tauri::api::path;
|
||||
use tauri::Manager;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos;
|
||||
mod menu;
|
||||
mod window;
|
||||
|
||||
use window::WindowExt;
|
||||
|
||||
#[tauri::command(async)]
|
||||
async fn client_query_transport(
|
||||
|
@ -42,13 +42,6 @@ async fn app_ready(app_handle: tauri::AppHandle) {
|
|||
let window = app_handle.get_window("main").unwrap();
|
||||
|
||||
window.show().unwrap();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
println!("fixing shadow for, {:?}", window.ns_window().unwrap());
|
||||
window.fix_shadow();
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
|
@ -71,6 +64,11 @@ async fn main() {
|
|||
.setup(|app| {
|
||||
let app = app.handle();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
macos::lock_app_theme(AppThemeType::Dark as _);
|
||||
}
|
||||
|
||||
app.windows().iter().for_each(|(_, window)| {
|
||||
window.hide().unwrap();
|
||||
|
||||
|
@ -78,7 +76,13 @@ async fn main() {
|
|||
window.set_decorations(true).unwrap();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
window.set_transparent_titlebar(true, true);
|
||||
{
|
||||
use macos::*;
|
||||
|
||||
let window = window.ns_window().unwrap();
|
||||
set_titlebar_style(window, true, true);
|
||||
blur_window_background(window);
|
||||
}
|
||||
});
|
||||
|
||||
// core event transport
|
||||
|
@ -104,7 +108,6 @@ async fn main() {
|
|||
Ok(())
|
||||
})
|
||||
.on_menu_event(|event| menu::handle_menu_event(event))
|
||||
.on_window_event(|event| window::handle_window_event(event))
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
client_query_transport,
|
||||
client_command_transport,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{env::consts, ffi::c_void};
|
||||
use std::env::consts;
|
||||
|
||||
use tauri::{AboutMetadata, CustomMenuItem, Menu, MenuItem, Submenu, WindowMenuEvent, Wry};
|
||||
|
||||
|
@ -95,10 +95,11 @@ pub(crate) fn handle_menu_event(event: WindowMenuEvent<Wry>) {
|
|||
.window()
|
||||
.with_webview(|webview| {
|
||||
#[cfg(target_os = "macos")]
|
||||
unsafe {
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
let _result: c_void = msg_send![webview.inner(), reload];
|
||||
};
|
||||
{
|
||||
use crate::macos::reload_webview;
|
||||
|
||||
reload_webview(webview.inner() as _);
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
use tauri::{GlobalWindowEvent, Runtime, Window, Wry};
|
||||
|
||||
pub(crate) fn handle_window_event(event: GlobalWindowEvent<Wry>) {
|
||||
match event.event() {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WindowExt {
|
||||
#[cfg(target_os = "macos")]
|
||||
fn set_toolbar(&self, shown: bool);
|
||||
#[cfg(target_os = "macos")]
|
||||
fn set_transparent_titlebar(&self, transparent: bool, large: bool);
|
||||
#[cfg(target_os = "macos")]
|
||||
fn fix_shadow(&self);
|
||||
}
|
||||
|
||||
impl<R: Runtime> WindowExt for Window<R> {
|
||||
#[cfg(target_os = "macos")]
|
||||
fn set_toolbar(&self, shown: bool) {
|
||||
use cocoa::{
|
||||
appkit::{NSToolbar, NSWindow},
|
||||
base::{nil, NO},
|
||||
foundation::NSString,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let id = self.ns_window().unwrap() as cocoa::base::id;
|
||||
|
||||
if shown {
|
||||
let toolbar =
|
||||
NSToolbar::alloc(nil).initWithIdentifier_(NSString::alloc(nil).init_str("wat"));
|
||||
toolbar.setShowsBaselineSeparator_(NO);
|
||||
id.setToolbar_(toolbar);
|
||||
} else {
|
||||
id.setToolbar_(nil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn set_transparent_titlebar(&self, transparent: bool, large: bool) {
|
||||
use cocoa::{
|
||||
appkit::{NSWindow, NSWindowStyleMask, NSWindowTitleVisibility},
|
||||
base::{NO, YES},
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let id = self.ns_window().unwrap() as cocoa::base::id;
|
||||
|
||||
let mut style_mask = id.styleMask();
|
||||
// println!("existing style mask, {:#?}", style_mask);
|
||||
style_mask.set(
|
||||
NSWindowStyleMask::NSFullSizeContentViewWindowMask,
|
||||
transparent,
|
||||
);
|
||||
style_mask.set(
|
||||
NSWindowStyleMask::NSTexturedBackgroundWindowMask,
|
||||
transparent,
|
||||
);
|
||||
style_mask.set(
|
||||
NSWindowStyleMask::NSUnifiedTitleAndToolbarWindowMask,
|
||||
transparent && large,
|
||||
);
|
||||
id.setStyleMask_(style_mask);
|
||||
|
||||
if large {
|
||||
self.set_toolbar(true);
|
||||
}
|
||||
|
||||
id.setTitleVisibility_(if transparent {
|
||||
NSWindowTitleVisibility::NSWindowTitleHidden
|
||||
} else {
|
||||
NSWindowTitleVisibility::NSWindowTitleVisible
|
||||
});
|
||||
|
||||
id.setTitlebarAppearsTransparent_(if transparent { YES } else { NO });
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn fix_shadow(&self) {
|
||||
use cocoa::appkit::NSWindow;
|
||||
|
||||
unsafe {
|
||||
let id = self.ns_window().unwrap() as cocoa::base::id;
|
||||
|
||||
println!("recomputing shadow for window {:?}", id.title());
|
||||
|
||||
id.invalidateShadow();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
{
|
||||
"name": "@sd/landing",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "npm run server",
|
||||
"prod": "npm run build && npm run server:prod",
|
||||
"dev": "pnpm run server",
|
||||
"prod": "pnpm run build && pnpm run server:prod",
|
||||
"vercel-build": "./vercel/deploy.sh",
|
||||
"build": "vite build && vite build --ssr && vite-plugin-ssr prerender",
|
||||
"server": "ts-node ./server",
|
||||
|
|
|
@ -83,7 +83,7 @@ function Page() {
|
|||
<div className="mt-24 lg:mt-5" />
|
||||
<NewBanner
|
||||
headline="Spacedrive raises $2M led by OSS Capital"
|
||||
href="https://spacedrive.com/blog/spacedrive-funding-announcement"
|
||||
href="/blog/spacedrive-funding-announcement"
|
||||
link="Read post"
|
||||
/>
|
||||
{unsubscribedFromWaitlist && (
|
||||
|
@ -97,7 +97,7 @@ function Page() {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<h1 className="z-30 px-2 mb-3 text-4xl text-white font-black leading-tight text-center fade-in-heading md:text-6xl">
|
||||
<h1 className="z-30 px-2 mb-3 text-4xl font-black leading-tight text-center text-white fade-in-heading md:text-6xl">
|
||||
A file explorer from the future.
|
||||
</h1>
|
||||
<p className="z-30 max-w-4xl mt-1 mb-8 text-center animation-delay-1 fade-in-heading text-md lg:text-lg leading-2 lg:leading-8 text-gray-450">
|
||||
|
|
|
@ -48,7 +48,7 @@ html {
|
|||
|
||||
.fade-in-whats-new {
|
||||
animation: fadeInDown 1s forwards;
|
||||
animation-delay: 1.5s;
|
||||
animation-delay: 600ms;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ impl Job for FileIdentifierJob {
|
|||
})
|
||||
.await?;
|
||||
|
||||
let remaining = count_orphan_file_paths(&ctx.core_ctx, location.id.into()).await?;
|
||||
let _remaining = count_orphan_file_paths(&ctx.core_ctx, location.id.into()).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ function AppLayout() {
|
|||
return false;
|
||||
}}
|
||||
className={clsx(
|
||||
'flex flex-row h-screen overflow-hidden text-gray-900 bg-white select-none dark:text-white dark:bg-gray-650',
|
||||
'flex flex-row h-screen overflow-hidden text-gray-900 select-none dark:text-white',
|
||||
isWindowRounded && 'rounded-xl',
|
||||
hasWindowBorder && 'border border-gray-200 dark:border-gray-500'
|
||||
)}
|
||||
|
@ -84,7 +84,7 @@ function AppLayout() {
|
|||
<div className="flex flex-col w-full min-h-full">
|
||||
{/* <TopBar /> */}
|
||||
|
||||
<div className="relative flex w-full">
|
||||
<div className="relative flex w-full min-h-full bg-white dark:bg-gray-650">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -21,7 +21,7 @@ export const SidebarLink = (props: NavLinkProps & { children: React.ReactNode })
|
|||
{({ isActive }) => (
|
||||
<span
|
||||
className={clsx(
|
||||
'max-w mb-[2px] text-gray-550 dark:text-gray-150 rounded px-2 py-1 flex flex-row flex-grow items-center font-medium hover:bg-gray-100 dark:hover:bg-gray-600 text-sm',
|
||||
'max-w mb-[2px] text-gray-550 dark:text-gray-150 rounded px-2 py-1 flex flex-row flex-grow items-center font-medium text-sm',
|
||||
{
|
||||
'!bg-primary !text-white hover:bg-primary dark:hover:bg-primary': isActive
|
||||
},
|
||||
|
@ -69,6 +69,10 @@ export function MacWindowControls() {
|
|||
);
|
||||
}
|
||||
|
||||
// cute little helper to decrease code clutter
|
||||
const macOnly = (platform: string | undefined, classnames: string) =>
|
||||
platform === 'macOS' ? classnames : '';
|
||||
|
||||
export const Sidebar: React.FC<SidebarProps> = (props) => {
|
||||
const { isExperimental } = useNodeStore();
|
||||
|
||||
|
@ -87,7 +91,14 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
|
|||
];
|
||||
|
||||
return (
|
||||
<div className="flex flex-col flex-grow-0 flex-shrink-0 w-48 min-h-full px-2.5 overflow-x-hidden overflow-y-scroll border-r border-gray-100 no-scrollbar bg-gray-50 dark:bg-gray-850 dark:border-gray-600">
|
||||
<div
|
||||
className={clsx(
|
||||
'flex flex-col flex-grow-0 flex-shrink-0 w-48 min-h-full px-2.5 overflow-x-hidden overflow-y-scroll border-r border-gray-100 no-scrollbar bg-gray-50 dark:bg-gray-850 dark:border-gray-600',
|
||||
{
|
||||
'dark:!bg-opacity-40': appProps?.platform === 'macOS'
|
||||
}
|
||||
)}
|
||||
>
|
||||
{appProps?.platform === 'browser' && window.location.search.includes('showControls') ? (
|
||||
<MacWindowControls />
|
||||
) : null}
|
||||
|
@ -96,19 +107,32 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
|
|||
<Dropdown
|
||||
buttonProps={{
|
||||
justifyLeft: true,
|
||||
className: `flex w-full text-left max-w-full mb-1 mt-1 -mr-0.5 shadow-xs rounded
|
||||
className: clsx(
|
||||
`flex w-full text-left max-w-full mb-1 mt-1 -mr-0.5 shadow-xs rounded
|
||||
!bg-gray-50
|
||||
border-gray-150
|
||||
hover:!bg-gray-1000
|
||||
|
||||
dark:!bg-gray-550
|
||||
dark:hover:!bg-gray-550
|
||||
|
||||
dark:!border-gray-550
|
||||
dark:hover:!border-gray-500`,
|
||||
|
||||
dark:!bg-gray-500
|
||||
dark:hover:!bg-gray-500
|
||||
|
||||
dark:!border-gray-550
|
||||
dark:hover:!border-gray-500
|
||||
`,
|
||||
appProps?.platform === 'macOS' &&
|
||||
'dark:!bg-opacity-40 dark:hover:!bg-opacity-70 dark:!border-[#333949] dark:hover:!border-[#394052]'
|
||||
),
|
||||
|
||||
variant: 'gray'
|
||||
}}
|
||||
// buttonIcon={<Book weight="bold" className="w-4 h-4 mt-0.5 mr-1" />}
|
||||
// to support the transparent sidebar on macOS we use slightly adjusted styles
|
||||
itemsClassName={macOnly(appProps?.platform, 'dark:bg-gray-800 dark:divide-gray-600')}
|
||||
itemButtonClassName={macOnly(
|
||||
appProps?.platform,
|
||||
'dark:hover:bg-gray-550 dark:hover:bg-opacity-50'
|
||||
)}
|
||||
// this shouldn't default to "My Library", it is only this way for landing demo
|
||||
// TODO: implement demo mode for the sidebar and show loading indicator instead of "My Library"
|
||||
buttonText={clientState?.node_name || 'My Library'}
|
||||
items={[
|
||||
[
|
||||
|
@ -146,11 +170,6 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
|
|||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
||||
{/* <SidebarLink to="explorer">
|
||||
<Icon component={MonitorPlay} />
|
||||
Explorer
|
||||
</SidebarLink> */}
|
||||
</div>
|
||||
<div>
|
||||
<Heading>Locations</Heading>
|
||||
|
@ -158,7 +177,7 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
|
|||
return (
|
||||
<div key={index} className="flex flex-row items-center">
|
||||
<NavLink
|
||||
className="'relative w-full group'"
|
||||
className="relative w-full group"
|
||||
to={{
|
||||
pathname: `explorer/${location.id}`
|
||||
}}
|
||||
|
@ -166,18 +185,18 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
|
|||
{({ isActive }) => (
|
||||
<span
|
||||
className={clsx(
|
||||
'max-w mb-[2px] text-gray-550 dark:text-gray-150 rounded px-2 py-1 flex flex-row flex-grow items-center hover:bg-gray-100 dark:hover:bg-gray-600 text-sm',
|
||||
'max-w mb-[2px] text-gray-550 dark:text-gray-150 rounded px-2 py-1 gap-2 flex flex-row flex-grow items-center truncate text-sm',
|
||||
{
|
||||
'!bg-primary !text-white hover:bg-primary dark:hover:bg-primary': isActive
|
||||
}
|
||||
)}
|
||||
>
|
||||
<div className="w-[18px] mr-2 -mt-0.5">
|
||||
<Folder className={clsx(!isActive && 'hidden')} white />
|
||||
<Folder className={clsx(isActive && 'hidden')} />
|
||||
<div className="-mt-0.5 flex-grow-0 flex-shrink-0">
|
||||
<Folder size={18} className={clsx(!isActive && 'hidden')} white />
|
||||
<Folder size={18} className={clsx(isActive && 'hidden')} />
|
||||
</div>
|
||||
{location.name}
|
||||
<div className="flex-grow" />
|
||||
|
||||
<span className="flex-grow flex-shrink-0">{location.name}</span>
|
||||
</span>
|
||||
)}
|
||||
</NavLink>
|
||||
|
@ -191,7 +210,7 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
|
|||
createLocation({ path: result });
|
||||
});
|
||||
}}
|
||||
className="w-full px-2 py-1.5 mt-1 text-xs font-bold text-center text-gray-400 dark:text-gray-500 border border-dashed rounded border-transparent cursor-normal border-gray-350 dark:border-gray-550 hover:dark:border-gray-500 transition"
|
||||
className="w-full px-2 py-1.5 mt-1 text-xs font-bold text-center text-gray-400 dark:text-gray-400 border border-dashed rounded border-transparent cursor-normal border-gray-350 dark:border-gray-450 hover:dark:border-gray-400 transition"
|
||||
>
|
||||
Add Location
|
||||
</button>
|
||||
|
|
|
@ -13,12 +13,21 @@ interface FolderProps {
|
|||
* Render a white folder icon
|
||||
*/
|
||||
white?: boolean;
|
||||
|
||||
/**
|
||||
* The size of the icon to show -- uniform width and height
|
||||
*/
|
||||
size?: number;
|
||||
}
|
||||
|
||||
export function Folder(props: FolderProps) {
|
||||
const { size = 24 } = props;
|
||||
|
||||
return (
|
||||
<img
|
||||
className={props.className}
|
||||
width={size}
|
||||
height={size}
|
||||
src={props.white ? folderWhiteSvg : folderSvg}
|
||||
alt="Folder icon"
|
||||
/>
|
||||
|
|
|
@ -153,7 +153,7 @@ export const OverviewScreen = () => {
|
|||
<div className="flex flex-col w-full h-screen overflow-x-hidden custom-scroll page-scroll">
|
||||
<div data-tauri-drag-region className="flex flex-shrink-0 w-full h-5" />
|
||||
{/* PAGE */}
|
||||
<div className="flex flex-col w-full h-screen px-3">
|
||||
<div className="flex flex-col w-full h-screen px-4">
|
||||
{/* STAT HEADER */}
|
||||
<div className="flex w-full">
|
||||
{/* STAT CONTAINER */}
|
||||
|
|
|
@ -20,6 +20,7 @@ export interface DropdownProps {
|
|||
buttonIcon?: any;
|
||||
className?: string;
|
||||
itemsClassName?: string;
|
||||
itemButtonClassName?: string;
|
||||
}
|
||||
|
||||
export const Dropdown: React.FC<DropdownProps> = (props) => {
|
||||
|
@ -64,7 +65,8 @@ export const Dropdown: React.FC<DropdownProps> = (props) => {
|
|||
{
|
||||
'bg-gray-300 dark:!bg-gray-500 dark:hover:bg-gray-500': button.selected
|
||||
// 'text-gray-900 dark:text-gray-200': !active
|
||||
}
|
||||
},
|
||||
props.itemButtonClassName
|
||||
)}
|
||||
>
|
||||
{button.icon && (
|
||||
|
|
Loading…
Reference in a new issue