8 Commits

Author SHA1 Message Date
kenji bcad6c2f69 docs: add FIXME for calculator 2026-01-11 13:59:28 -06:00
kenji 0940fd31d7 fix(swayosd): added auto-restart functionality 2026-01-11 13:59:21 -06:00
kenji 9fc1763073 feat(textfox): updated rev 2026-01-11 13:54:21 -06:00
kenji 3d51e1db83 feat(firefox): now uses web-app for versatility 2026-01-11 13:53:48 -06:00
kenji 992ca558dd feat(swayimg): wrapper dynamically adjust image size without overlapping waybar 2026-01-11 13:24:45 -06:00
kenji 72c94dbd63 fix(yazi): expanded image_bound for versatilty 2026-01-11 13:09:57 -06:00
kenji 0a4bfdfab8 remove(apps): imv replaced by yazi 2026-01-11 13:09:18 -06:00
kenji cfbc56ab6d remove(firefox): web-app css set to default, awaiting textfox migration 2026-01-11 13:09:04 -06:00
8 changed files with 210 additions and 127 deletions
+8 -2
View File
@@ -18,8 +18,8 @@
];
workspace = [
"special:youtube, on-created-empty:uwsm app -- firefox -P YouTube --name youtube"
"special:jellyfin, on-created-empty:uwsm app -- firefox -P Jellyfin --name jellyfin"
"special:youtube, on-created-empty:uwsm app -- firefox -P web-app --name youtube https://youtube.com"
"special:jellyfin, on-created-empty:uwsm app -- firefox -P web-app --name jellyfin https://watch.sakamoto.dev"
];
windowrulev2 = [
@@ -68,6 +68,12 @@
name = "Jellyfin";
url = "https://watch.sakamoto.dev";
};
web-app = import ./profiles/web-app.nix {
inherit pkgs myConfig;
id = 3;
name = "web-app";
url = "about:blank";
};
hakase = {
search.force = true;
isDefault = true;
+105 -104
View File
@@ -17,6 +17,7 @@
bitwarden
tridactyl
new-tab-override
pywalfox
];
settings = {
@@ -37,6 +38,7 @@
"widget.use-xdg-desktop-portal.file-picker" = 1; # Use native file picker
# --- UI & Behavior ---
"browser.toolbars.bookmarks.visibility" = "never";
"browser.compactmode.show" = true;
"browser.tabs.closeWindowWithLastTab" = false;
"extensions.pocket.enabled" = false;
@@ -70,108 +72,107 @@
"network.trr.mode" = 2; # Use DoH with system fallback
"network.trr.uri" = "https://dns.quad9.net/dns-query";
};
userChrome = ''
/* --- Autohide Entire Toolbox (Tabs + Address Bar) --- */
/* Adapted from MrOtherGuy's autohide_main_toolbar.css */
:root{
/* Height of Tabs + Nav Bar approx 80px */
--uc-navbar-transform: -85px;
--uc-autohide-toolbar-delay: 0.1s;
--uc-autohide-toolbar-duration: 200ms;
}
:root[uidensity="compact"]{ --uc-navbar-transform: -70px }
#navigator-toolbox > div{ display: contents; }
/* Apply transform to TabsToolbar AND Nav-bar */
:root[sessionrestored] :where(#nav-bar,#PersonalToolbar,#TabsToolbar,#tab-notification-deck,.global-notificationbox,#notifications-toolbar){
transform: translateY(var(--uc-navbar-transform))
}
:root:is([customizing],[chromehidden*="toolbar"]) :where(#nav-bar,#PersonalToolbar,#TabsToolbar,#tab-notification-deck,.global-notificationbox,#notifications-toolbar){
transform: none !important;
opacity: 1 !important;
}
/* Hide styles for Nav-Bar AND TabsToolbar */
:where(#nav-bar,#TabsToolbar):not([customizing]){
opacity: 0;
transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay) !important;
position: relative;
z-index: 2;
background-color: #1c1b22 !important; /* Solid background */
}
#navigator-toolbox,
#sidebar-box,
#sidebar-main,
#sidebar-splitter,
#tabbrowser-tabbox{
z-index: auto !important;
}
/* Show when toolbox is focused or hovered */
#navigator-toolbox:focus-within > .browser-toolbar,
.browser-titlebar:hover ~ :is(#nav-bar,#PersonalToolbar,#TabsToolbar),
#nav-bar:hover,
#TabsToolbar:hover,
#nav-bar:hover + #PersonalToolbar{
transform: translateY(0);
opacity: 1;
transition-duration: var(--uc-autohide-toolbar-duration), var(--uc-autohide-toolbar-duration) !important;
transition-delay: 0s !important;
}
/* Ensure popups still work (URL bar) */
:root[sessionrestored] #urlbar[popover]{
opacity: 0;
pointer-events: none;
transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay);
transform: translateY(var(--uc-navbar-transform));
}
#mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#selection-shortcut-action-panel,#chat-shortcuts-options-panel,#tab-preview-panel)) ~ toolbox #urlbar[popover],
.browser-titlebar:is(:hover,:focus-within) ~ #nav-bar #urlbar[popover],
#nav-bar:is(:hover,:focus-within) #urlbar[popover],
#urlbar-container > #urlbar[popover]:is([focused],[open]){
opacity: 1;
pointer-events: auto;
transition-delay: 0ms;
transform: translateY(0);
}
:where(:root[sessionrestored]) #urlbar-container > #urlbar[popover]:is([focused],[open]){
transition-duration: 100ms;
}
/* --- CRITICAL FIX: Trigger Zone --- */
/* Since we hide EVERYTHING, we need a hitbox at the top of the screen */
#navigator-toolbox::after {
content: "";
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 20px; /* Generous hit target */
z-index: 10000;
pointer-events: auto;
}
/* When hitbox is hovered, reveal bars */
#navigator-toolbox:hover :where(#nav-bar,#PersonalToolbar,#TabsToolbar) {
transform: translateY(0) !important;
opacity: 1 !important;
transition-delay: 0s !important;
}
/* Move up the content view to fill the gap */
:root[sessionrestored]:not([chromehidden~="toolbar"]) > body > #browser{
margin-top: var(--uc-navbar-transform);
}
/* Fix Titlebar and Bookmarks */
#titlebar { appearance: none !important; }
#PersonalToolbar { visibility: collapse !important; }
'';
#
# userChrome = ''
# /* --- Autohide Entire Toolbox (Tabs + Address Bar) --- */
# /* Adapted from MrOtherGuy's autohide_main_toolbar.css */
#
# :root{
# /* Height of Tabs + Nav Bar approx 80px */
# --uc-navbar-transform: -85px;
# --uc-autohide-toolbar-delay: 0.1s;
# --uc-autohide-toolbar-duration: 200ms;
# }
# :root[uidensity="compact"]{ --uc-navbar-transform: -70px }
#
# #navigator-toolbox > div{ display: contents; }
#
# /* Apply transform to TabsToolbar AND Nav-bar */
# :root[sessionrestored] :where(#nav-bar,#PersonalToolbar,#TabsToolbar,#tab-notification-deck,.global-notificationbox,#notifications-toolbar){
# transform: translateY(var(--uc-navbar-transform))
# }
#
# :root:is([customizing],[chromehidden*="toolbar"]) :where(#nav-bar,#PersonalToolbar,#TabsToolbar,#tab-notification-deck,.global-notificationbox,#notifications-toolbar){
# transform: none !important;
# opacity: 1 !important;
# }
#
# /* Hide styles for Nav-Bar AND TabsToolbar */
# :where(#nav-bar,#TabsToolbar):not([customizing]){
# opacity: 0;
# transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay) !important;
# position: relative;
# z-index: 2;
# background-color: #1c1b22 !important; /* Solid background */
# }
#
# #navigator-toolbox,
# #sidebar-box,
# #sidebar-main,
# #sidebar-splitter,
# #tabbrowser-tabbox{
# z-index: auto !important;
# }
#
# /* Show when toolbox is focused or hovered */
# #navigator-toolbox:focus-within > .browser-toolbar,
# .browser-titlebar:hover ~ :is(#nav-bar,#PersonalToolbar,#TabsToolbar),
# #nav-bar:hover,
# #TabsToolbar:hover,
# #nav-bar:hover + #PersonalToolbar{
# transform: translateY(0);
# opacity: 1;
# transition-duration: var(--uc-autohide-toolbar-duration), var(--uc-autohide-toolbar-duration) !important;
# transition-delay: 0s !important;
# }
#
# /* Ensure popups still work (URL bar) */
# :root[sessionrestored] #urlbar[popover]{
# opacity: 0;
# pointer-events: none;
# transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay);
# transform: translateY(var(--uc-navbar-transform));
# }
# #mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#selection-shortcut-action-panel,#chat-shortcuts-options-panel,#tab-preview-panel)) ~ toolbox #urlbar[popover],
# .browser-titlebar:is(:hover,:focus-within) ~ #nav-bar #urlbar[popover],
# #nav-bar:is(:hover,:focus-within) #urlbar[popover],
# #urlbar-container > #urlbar[popover]:is([focused],[open]){
# opacity: 1;
# pointer-events: auto;
# transition-delay: 0ms;
# transform: translateY(0);
# }
# :where(:root[sessionrestored]) #urlbar-container > #urlbar[popover]:is([focused],[open]){
# transition-duration: 100ms;
# }
#
# /* --- CRITICAL FIX: Trigger Zone --- */
# /* Since we hide EVERYTHING, we need a hitbox at the top of the screen */
# #navigator-toolbox::after {
# content: "";
# position: fixed;
# top: 0;
# left: 0;
# width: 100%;
# height: 20px; /* Generous hit target */
# z-index: 10000;
# pointer-events: auto;
# }
#
# /* When hitbox is hovered, reveal bars */
# #navigator-toolbox:hover :where(#nav-bar,#PersonalToolbar,#TabsToolbar) {
# transform: translateY(0) !important;
# opacity: 1 !important;
# transition-delay: 0s !important;
# }
#
# /* Move up the content view to fill the gap */
# :root[sessionrestored]:not([chromehidden~="toolbar"]) > body > #browser{
# margin-top: var(--uc-navbar-transform);
# }
#
# /* Fix Titlebar and Bookmarks */
# #titlebar { appearance: none !important; }
# #PersonalToolbar { visibility: collapse !important; }
# '';
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
textfox = {
enable = true;
profile = "hakase";
profiles = ["hakase" "web-app"];
config = {
# background = {
# color = "#123456";
+71 -13
View File
@@ -1,23 +1,81 @@
{pkgs, ...}: {
home.packages = with pkgs; [imv];
{pkgs, ...}: let
# Max window size (leave room for waybar/hyprbars)
maxW = 2800;
maxH = 1100;
swayimg-wrapper = pkgs.writeShellScriptBin "swayimg-wrapper" ''
if [ -z "$1" ]; then
exec ${pkgs.swayimg}/bin/swayimg
fi
# Get image dimensions
dims=$(${pkgs.file}/bin/file -b "$1" | ${pkgs.gnugrep}/bin/grep -oP '\d+ ?x ?\d+' | head -1 | tr -d ' ')
if [ -z "$dims" ]; then
# Fallback if file doesn't report dimensions
exec ${pkgs.swayimg}/bin/swayimg "$@"
fi
imgW=$(echo "$dims" | cut -dx -f1)
imgH=$(echo "$dims" | cut -dx -f2)
# Calculate scale to fit within max bounds while preserving aspect ratio
scaleW=$(echo "scale=4; ${toString maxW} / $imgW" | ${pkgs.bc}/bin/bc)
scaleH=$(echo "scale=4; ${toString maxH} / $imgH" | ${pkgs.bc}/bin/bc)
# Use the smaller scale factor
if [ $(echo "$scaleW < $scaleH" | ${pkgs.bc}/bin/bc) -eq 1 ]; then
scale=$scaleW
else
scale=$scaleH
fi
# Only scale down, not up
if [ $(echo "$scale >= 1" | ${pkgs.bc}/bin/bc) -eq 1 ]; then
exec ${pkgs.swayimg}/bin/swayimg "$@"
fi
# Calculate new size
newW=$(echo "$imgW * $scale / 1" | ${pkgs.bc}/bin/bc)
newH=$(echo "$imgH * $scale / 1" | ${pkgs.bc}/bin/bc)
exec ${pkgs.swayimg}/bin/swayimg --size="$newW,$newH" "$@"
'';
in {
home.packages = [pkgs.swayimg swayimg-wrapper];
xdg.mimeApps = {
enable = true;
defaultApplications = {
"image/png" = "imv.desktop";
"image/jpeg" = "imv.desktop";
"image/gif" = "imv.desktop";
"image/webp" = "imv.desktop";
"image/bmp" = "imv.desktop";
"image/svg+xml" = "imv.desktop";
"image/tiff" = "imv.desktop";
"image/png" = "swayimg-wrapper.desktop";
"image/jpeg" = "swayimg-wrapper.desktop";
"image/gif" = "swayimg-wrapper.desktop";
"image/webp" = "swayimg-wrapper.desktop";
"image/bmp" = "swayimg-wrapper.desktop";
"image/svg+xml" = "swayimg-wrapper.desktop";
"image/tiff" = "swayimg-wrapper.desktop";
};
};
xdg.desktopEntries.swayimg-wrapper = {
name = "Swayimg";
exec = "swayimg-wrapper %f";
terminal = false;
type = "Application";
mimeType = ["image/png" "image/jpeg" "image/gif" "image/webp" "image/bmp" "image/svg+xml" "image/tiff"];
};
# swayimg config
xdg.configFile."swayimg/config".text = ''
[viewer]
scale = fit
[info]
show = no
'';
wayland.windowManager.hyprland.settings.windowrulev2 = [
# --- IMAGE VIEWER (IMV) ---
"float, class:^(imv)$"
"center, class:^(imv)$"
"size 70% 70%, class:^(imv)$"
# --- IMAGE VIEWER (swayimg) ---
"float, class:^(swayimg)$"
"center, class:^(swayimg)$"
];
}
+17 -4
View File
@@ -1,10 +1,23 @@
{pkgs, ...}: {
{
pkgs,
lib,
...
}: {
services.swayosd.enable = true;
# Auto-restart swayosd on crash
systemd.user.services.swayosd = {
Unit = {
StartLimitBurst = lib.mkForce 5;
StartLimitIntervalSec = lib.mkForce 30;
};
Service = {
Restart = lib.mkForce "on-failure";
RestartSec = lib.mkForce "100ms";
};
};
wayland.windowManager.hyprland.settings = {
exec-once = [
"uwsm app -- swayosd-server"
];
bindel = [
", XF86AudioRaiseVolume, exec, swayosd-client --output-volume raise"
", XF86AudioLowerVolume, exec, swayosd-client --output-volume lower"
+1
View File
@@ -79,6 +79,7 @@ in {
bindd = [
"SUPER, SPACE, Open Vicinae, exec, vicinae-toggle"
"SUPER, period, Open Emoji Picker, exec, vicinae-toggle deeplink vicinae://extensions/vicinae/core/search-emojis"
# FIXME: calculator history does not allow you to calculate
"SUPER, C, Open Calculator, exec, vicinae-toggle deeplink vicinae://extensions/vicinae/calculator/history"
"SUPER, V, Open Clipboard History, exec, vicinae-toggle deeplink vicinae://extensions/vicinae/clipboard/history"
];
+4
View File
@@ -4,6 +4,7 @@
...
}: let
# Yazi wrapper for xdg-desktop-portal-termfilechooser
# TODO: rewrite in the future
yaziWrapper = pkgs.writeShellScript "yazi-wrapper.sh" ''
if [[ "$6" == "1" ]]; then
set -x
@@ -80,6 +81,9 @@ in {
sort_dir_first = true;
linemode = "size";
};
tasks = {
image_bound = [10000 10000];
};
};
};
Generated
+3 -3
View File
@@ -1038,11 +1038,11 @@
]
},
"locked": {
"lastModified": 1763730250,
"narHash": "sha256-OPlKRltdA2iIm70Nw/kWt5FnwxR1xmxC44tqGUX7Hro=",
"lastModified": 1767427579,
"narHash": "sha256-q9aFfPohbMS6ehkQHReMeIjtld0wGiUsxlHoPRRvsp4=",
"owner": "adriankarlen",
"repo": "textfox",
"rev": "2f385d16abab56984b874627ca0dd4f3ca7ae4ac",
"rev": "29c31979e5583d9367247f0af8675f88482ff481",
"type": "github"
},
"original": {