Skip to content

Commit

Permalink
Merge pull request #7 from edelvarden/master
Browse files Browse the repository at this point in the history
UI fixes
  • Loading branch information
0-don authored Apr 28, 2024
2 parents 6a6e147 + 19e452d commit a10b48c
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 65 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
},
"dependencies": {
"@tauri-apps/api": "^1.5.3",
"color-convert": "^2.0.1",
"dayjs": "^1.11.10",
"solid-icons": "^1.1.0",
"solid-js": "^1.8.16"
},
"devDependencies": {
"@tauri-apps/cli": "^1.5.11",
"@types/color-convert": "^2.0.3",
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"prettier": "^3.2.5",
Expand Down
103 changes: 59 additions & 44 deletions src-tauri/src/service/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::connection;
use alloc::borrow::Cow;
use arboard::ImageData;
use entity::clipboard::{self, ActiveModel, Model};
use migration::IntoIndexColumn;
use sea_orm::{
ActiveModelTrait, ColumnTrait, DbErr, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder,
QuerySelect, QueryTrait, Set,
Expand Down Expand Up @@ -48,50 +49,64 @@ pub async fn get_clipboards_db(
) -> Result<Vec<Model>, DbErr> {
let db = connection::establish_connection().await?;

let model = clipboard::Entity::find()
.apply_if(star, |query, starred| {
query.filter(clipboard::Column::Star.eq(starred))
})
.apply_if(search, |query, content| {
// Use match statement for cleaner logic
let filter = match content.as_str() {
"txt" | "text" => clipboard::Column::Content
.contains(&content)
.or(clipboard::Column::Type.eq("text")),

"img" | "image" => clipboard::Column::Content
.contains(&content)
.or(clipboard::Column::Type.eq("image")),

"lnk" | "link" => clipboard::Column::Content
.contains(&content)
.or(clipboard::Column::Type.eq("link")),

"clr" | "color" | "colour" => clipboard::Column::Content
.contains(&content)
.or(clipboard::Column::Type.eq("hex"))
.or(clipboard::Column::Type.eq("rgb")),

"hex" => clipboard::Column::Content
.contains(&content)
.or(clipboard::Column::Type.eq("hex")),

"rgb" => clipboard::Column::Content
.contains(&content)
.or(clipboard::Column::Type.eq("rgb")),

_ => clipboard::Column::Content.contains(&content),
};
query.filter(filter)
})
.apply_if(img, |query, _| {
query.filter(clipboard::Column::Type.eq("image"))
})
.offset(cursor)
.limit(10)
.order_by_desc(clipboard::Column::Id)
.all(&db)
.await?;
let mut query = clipboard::Entity::find();

// filter to get only pinned entries
if let Some(starred) = star {
query = query.filter(clipboard::Column::Star.eq(starred));
}

// filter to get only images
if let Some(img) = img {
query = query.filter(clipboard::Column::Type.eq("image"));
}

// smart search
if let Some(content) = search {

// display text entries
let filter = if content == "txt" || content == "text" {
clipboard::Column::Content.contains(&content)
.or(clipboard::Column::Type.eq("text"))

// display image entries
} else if content == "img" || content == "image" {
clipboard::Column::Content.contains(&content)
.or(clipboard::Column::Type.eq("image"))

// display link entries
} else if content == "lnk" || content == "link" {
clipboard::Column::Content.contains(&content)
.or(clipboard::Column::Type.eq("link"))

// display color entries
} else if content == "clr" || content == "color" {
clipboard::Column::Content.contains(&content)
.or(clipboard::Column::Type.eq("hex"))
.or(clipboard::Column::Type.eq("rgb"))
} else if content == "hex" {
clipboard::Column::Content.contains(&content)
.or(clipboard::Column::Type.eq("hex"))
} else if content == "rgb" {
clipboard::Column::Content.contains(&content)
.or(clipboard::Column::Type.eq("rgb"))

// use default search
} else {
clipboard::Column::Content.contains(&content)
};

query = query.filter(filter)
.order_by_desc(clipboard::Column::Content.starts_with(&content));

} else {
// order the results by creation time by default
query = query.order_by_desc(clipboard::Column::Id);
}

query = query.offset(cursor).limit(10);

let model = query.all(&db).await?;

let parsed_model: Vec<Model> = model
.into_iter()
Expand Down
29 changes: 17 additions & 12 deletions src-tauri/src/utils/clipboard_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,23 @@ impl ClipboardHelper<'_> {

let is_link = Regex::new(r"^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$").unwrap();
let is_hex = Regex::new(r"^#?(?:[0-9a-fA-F]{3}){1,2}(?:[0-9]{2})?$").unwrap();
let is_rgb = Regex::new(r"^(?:rgb|rgba|hsl|hsla|hwb)\((.*)\)").unwrap();

let r#type = if text.is_some() && is_link.is_match(text.as_ref().unwrap()) {
Set("link".to_string())
} else if text.is_some() && is_hex.is_match(text.as_ref().unwrap()) {
Set("hex".to_string())
} else if text.is_some() && is_rgb.is_match(text.as_ref().unwrap()) {
Set("rgb".to_string())
} else if text.is_some() {
Set("text".to_string())
} else {
Set("image".to_string())
let is_rgb = Regex::new(r"^(?:rgb|rgba|hsl|hsla|hsv|hwb)\((.*)\)").unwrap();

let r#type = match text {
Some(text) => {
if is_link.is_match(text) {
Set("link".to_string())
} else if is_hex.is_match(text) {
Set("hex".to_string())
} else if is_rgb.is_match(text) {
Set("rgb".to_string())
} else {
Set("text".to_string())
}
}
None => {
Set("image".to_string())
}
};

let active_model = if let Some(img) = image {
Expand Down
2 changes: 1 addition & 1 deletion src/components/navigation/SettingsTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const Tabs: Component<TabsProps> = ({}) => {

return (
<div class="border-b border-gray-500">
<nav class="-mb-px flex justify-center space-x-8">
<nav class="-mb-px flex justify-center gap-2">
<For each={tabs()}>
{({ Icon, current, name }) => (
<button
Expand Down
24 changes: 17 additions & 7 deletions src/components/pages/app/Clipboards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import clippy from "../../../assets/clippy.png";
import ClipboardStore from "../../../store/ClipboardStore";
import HotkeyStore from "../../../store/HotkeyStore";
import { formatBytes } from "../../../utils/helpers";
import { hsvToRgbString, hwbToRgbString } from "../../../utils/convertors";

dayjs.extend(utc);
dayjs.extend(relativeTime);
Expand Down Expand Up @@ -57,7 +58,7 @@ export const Clipboards: Component<ClipboardsProps> = ({}) => {
}}
class={`${
clipboard.star ? "text-yellow-400 dark:text-yellow-300" : "hidden text-zinc-700"
} z-10 text-xs hover:text-yellow-400 group-hover:block dark:text-white dark:hover:text-yellow-300`}
} z-10 h-2/4 w-8 py-2 text-xs hover:text-yellow-400 group-hover:block dark:text-white dark:hover:text-yellow-300`}
/>
<IoTrashOutline
onClick={async (e) => {
Expand All @@ -66,7 +67,7 @@ export const Clipboards: Component<ClipboardsProps> = ({}) => {
setClipboards((prev) => prev.filter((o) => o.id !== id));
}
}}
class="hidden text-xs text-zinc-700 hover:text-red-600 group-hover:block dark:text-white dark:hover:text-red-600"
class="hidden h-2/4 w-8 py-2 text-xs text-zinc-700 hover:text-red-600 group-hover:block dark:text-white dark:hover:text-red-600"
/>
</>
);
Expand All @@ -85,7 +86,7 @@ export const Clipboards: Component<ClipboardsProps> = ({}) => {
<Show when={scrollToTop()}>
<button
type="button"
class="absolute bottom-5 right-4 rounded-full bg-neutral-700 px-2 py-1 hover:bg-gray-500"
class="absolute bottom-5 right-4 z-10 rounded-full bg-neutral-600 px-2 py-1 hover:bg-gray-500"
onClick={() => clipboardRef()!.scrollTo(0, 0)}
>
<div class="relative flex items-center justify-center py-1">
Expand All @@ -106,7 +107,7 @@ export const Clipboards: Component<ClipboardsProps> = ({}) => {
return (
<button
type="button"
class="group w-full cursor-pointer select-none px-3 hover:bg-zinc-200 dark:hover:bg-neutral-700"
class="group relative w-full cursor-pointer select-none px-3 hover:bg-zinc-200 dark:hover:bg-neutral-700"
onClick={(e) => {
e.stopPropagation();

Expand Down Expand Up @@ -143,7 +144,13 @@ export const Clipboards: Component<ClipboardsProps> = ({}) => {
<div
class="h-5 w-5 rounded-md border border-solid border-zinc-400 dark:border-black"
style={{
"background-color": `${content}`,
"background-color": `${
content?.includes("hsv(")
? hsvToRgbString(content)
: content?.includes("hwb(")
? hwbToRgbString(content)
: content
}`,
}}
/>
)}
Expand All @@ -154,12 +161,13 @@ export const Clipboards: Component<ClipboardsProps> = ({}) => {
</Show>
</div>
</div>
<div class="truncate px-5">
<div class="mr-4 truncate px-4">
{clipboard.base64 ? (
<img
src={clipboard.base64}
width={width || 0}
height={height || 0}
class="max-h-52"
alt={`${width}x${height} ${size}`}
title={`${width}x${height} ${formatBytes(Number(size || "0"))}`}
/>
Expand All @@ -171,7 +179,9 @@ export const Clipboards: Component<ClipboardsProps> = ({}) => {
<div class="text-left text-xs text-zinc-400">{dayjs.utc(created_date!).fromNow()}</div>
</div>
</div>
<div class="flex w-12 flex-col items-end justify-between pl-1">{IconFunctions(clipboard)}</div>
<div class="absolute right-0 top-0 h-full w-full">
<div class="flex h-full flex-col items-end justify-start">{IconFunctions(clipboard)}</div>
</div>
</div>
<hr class="border-zinc-400 dark:border-zinc-700" />
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const Settings = () => {
onMount(() => listen("init", init));

return (
<div class="absolute flex h-full w-full flex-col bg-white text-black dark:bg-dark dark:text-white">
<div class="absolute flex h-full w-full flex-col overflow-x-hidden bg-white text-black dark:bg-dark dark:text-white">
<Tabs />
<div class="px-5 pt-5 dark:text-white">
<Show when={getCurrentTab()?.name === "General"}>
Expand Down
39 changes: 39 additions & 0 deletions src/utils/convertors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { hsv, hwb } from 'color-convert';

export function hsvToRgbString(hsvString: string): string {

// Parse HSV values from input string
const hsvRegex = /hsv\((\d+),\s*(\d+),\s*(\d+)\)/;
const match = hsvString.match(hsvRegex);
if (!match) {
return "";
}

const hue: number = parseInt(match[1]);
const saturation: number = parseInt(match[2]);
const value: number = parseInt(match[3]);

const [red, green, blue] = hsv.rgb([hue, saturation, value]);

const rgbString: string = `rgb(${red}, ${green}, ${blue})`;
return rgbString;
}

export function hwbToRgbString(hwbString: string): string {

// Parse HWB values from input string
const hwbRegex = /hwb\((\d+),\s*(\d+\.?\d*?)%,\s*(\d+\.?\d*?)%\)/;
const match = hwbString.match(hwbRegex);
if (!match) {
return "";
}

const hue: number = parseFloat(match[1]);
const whiteness: number = parseFloat(match[2]);
const blackness: number = parseFloat(match[3]);

const [red, green, blue] = hwb.rgb([hue, whiteness, blackness]);

const rgbString: string = `rgb(${red}, ${green}, ${blue})`;
return rgbString;
}

0 comments on commit a10b48c

Please sign in to comment.