Compare commits

...

3 Commits

Author SHA1 Message Date
Will Miao
237a015cde chore(release): bump version to v1.1.0 2026-06-12 23:38:16 +08:00
Will Miao
1ae2778baa feat(sidebar): add per-page hide toggle with more options dropdown
- Add ``` button in sidebar header with dropdown menu
- Add "Hide sidebar on this page" option with per-page localStorage state
- Show edge indicator (14px chevron) on left when hidden per-page
- Show brief toast notification when hiding
- Fix container margin not resetting when sidebar is per-page hidden
- Add i18n translations for all 10 locales
2026-06-12 18:27:54 +08:00
Will Miao
84fcdb5f20 fix(recipe): compute folder field on save to prevent reimported recipes disappearing from subfolder grid 2026-06-12 16:49:57 +08:00
16 changed files with 533 additions and 145 deletions

View File

@@ -6,22 +6,29 @@
"Scott R" "Scott R"
], ],
"allSupporters": [ "allSupporters": [
"Brennok",
"Insomnia Art Designs", "Insomnia Art Designs",
"2018cfh", "2018cfh",
"megakirbs", "megakirbs",
"Brennok", "Arlecchino Shion",
"Rob Williams",
"W+K+White", "W+K+White",
"wackop", "wackop",
"Phil", "Phil",
"Carl G.", "Carl G.",
"Arlecchino Shion",
"Charles Blakemore", "Charles Blakemore",
"Rob Williams",
"stone9k", "stone9k",
"itismyelement", "itismyelement",
"$MetaSamsara", "$MetaSamsara",
"Gingko Biloba",
"Kiba",
"onesecondinosaur", "onesecondinosaur",
"Christian Byrne",
"DM",
"Sen314",
"Estragon",
"Rosenthal", "Rosenthal",
"ClockDaemon",
"Francisco Tatis", "Francisco Tatis",
"Tobi_Swagg", "Tobi_Swagg",
"Andrew Wilson", "Andrew Wilson",
@@ -30,32 +37,38 @@
"JongWon Han", "JongWon Han",
"VantAI", "VantAI",
"runte3221", "runte3221",
"Illrigger",
"Tom Corrigan",
"FreelancerZ", "FreelancerZ",
"Echo",
"Robert Stacey",
"Edgar Tejeda", "Edgar Tejeda",
"Fraser Cross", "Fraser Cross",
"Liam MacDougal", "Liam MacDougal",
"Polymorphic Indeterminate", "Polymorphic Indeterminate",
"Sterilized",
"JORGE+LUIZ+HUSSNI+MESSIAS",
"Marc Whiffen", "Marc Whiffen",
"Skalabananen", "Skalabananen",
"Birdy", "Birdy",
"Kiba",
"Mozzel", "Mozzel",
"Gingko Biloba",
"Reno Lam", "Reno Lam",
"JSST",
"sig", "sig",
"Christian Byrne",
"DM",
"Sen314",
"Estragon",
"J\\B/ 8r0wns0n", "J\\B/ 8r0wns0n",
"Snaggwort", "Snaggwort",
"Takkan", "Takkan",
"Matt+J", "Matt+J",
"ClockDaemon", "Baekdoosixt",
"Jonathan Ross",
"KD", "KD",
"Omnidex", "Omnidex",
"Nazono_hito",
"daniel dove",
"Tyler Trebuchon", "Tyler Trebuchon",
"Release Cabrakan", "Release Cabrakan",
"JW Sin",
"Alex",
"SG", "SG",
"carozzz", "carozzz",
"James Dooley", "James Dooley",
@@ -70,77 +83,71 @@
"RedrockVP", "RedrockVP",
"Wolffen", "Wolffen",
"James Todd", "James Todd",
"Wicked Choices by ASLPro3D",
"Steven Pfeiffer", "Steven Pfeiffer",
"Tim", "レプサイ",
"Timmy", "Timmy",
"Johnny", "Johnny",
"Tak",
"Lisster", "Lisster",
"Michael Wong", "Michael Wong",
"Illrigger", "Big Red",
"whudunit", "whudunit",
"Tom Corrigan", "dl0901dm",
"JackieWang", "JackieWang",
"fnkylove", "fnkylove",
"Yushio", "Yushio",
"Vik71it", "Vik71it",
"Echo", "Bishoujoker",
"Lilleman", "Lilleman",
"Robert Stacey",
"PM", "PM",
"Todd Keck", "Todd Keck",
"Briton Heilbrun", "Briton Heilbrun",
"Jorge Hussni", "wildnut",
"Sterilized", "Aleksander Wujczyk",
"AM Kuro",
"BadassArabianMofo", "BadassArabianMofo",
"Pascal Dahle", "Pascal Dahle",
"quarz", "quarz",
"Greg", "Greg",
"JSST",
"lmsupporter", "lmsupporter",
"andrew.tappan",
"zounic", "zounic",
"wfpearl", "wfpearl",
"Baekdoosixt",
"Jonathan Ross",
"Jack B Nimble", "Jack B Nimble",
"Nazono_hito",
"Melville Parrish", "Melville Parrish",
"daniel dove",
"Lustre", "Lustre",
"JW Sin", "JaxMax",
"contrite831", "contrite831",
"Alex",
"bh", "bh",
"Marlon Daniels", "Marlon Daniels",
"Starkselle", "Starkselle",
"Aaron Bleuer", "Aaron Bleuer",
"LacesOut!", "LacesOut!",
"greebles", "greebles",
"Some Guy Named Barry",
"M Postkasse", "M Postkasse",
"Gooohokrbe", "Gooohokrbe",
"Wicked Choices by ASLPro3D",
"OldBones", "OldBones",
"Jacob Hoehler", "Jacob Hoehler",
"FinalyFree", "FinalyFree",
"Matt Wenzel",
"Weasyl", "Weasyl",
"Lex Song", "Lex Song",
"Cory Paza", "Cory Paza",
"Tak",
"Gonzalo Andre Allendes Lopez", "Gonzalo Andre Allendes Lopez",
"Zach Gonser", "Zach Gonser",
"Big Red",
"Jimmy Ledbetter", "Jimmy Ledbetter",
"Luc Job", "Luc Job",
"dl0901dm",
"Philip Hempel", "Philip Hempel",
"corde", "corde",
"Nick Walker", "Nick Walker",
"Bishoujoker", "dan",
"aai", "aai",
"Tori", "Tori",
"wildnut", "otaku fra",
"jean jahren", "jean jahren",
"Aleksander Wujczyk", "MiraiKuriyamaSy",
"AM Kuro",
"Ran C", "Ran C",
"ViperC", "ViperC",
"Penfore", "Penfore",
@@ -149,17 +156,22 @@
"Karl P.", "Karl P.",
"Akira_HentAI", "Akira_HentAI",
"Gordon Cole", "Gordon Cole",
"Adam Taylor",
"AbstractAss", "AbstractAss",
"andrew.tappan", "Weird_With_A_Beard",
"N/A", "N/A",
"The Spawn", "The Spawn",
"graysock", "graysock",
"Pozadine1",
"Qarob",
"AIGooner",
"Luc",
"Greenmoustache", "Greenmoustache",
"Jackthemind",
"fancypants", "fancypants",
"Eldithor", "Eldithor",
"Joboshy", "Joboshy",
"Digital", "Digital",
"JaxMax",
"takyamtom", "takyamtom",
"Bohemian Corporal", "Bohemian Corporal",
"Dan", "Dan",
@@ -170,42 +182,37 @@
"carey6409", "carey6409",
"Olive", "Olive",
"太郎 ゲーム", "太郎 ゲーム",
"Some Guy Named Barry", "Roslynd",
"jinxedx", "jinxedx",
"Cosmosis", "Cosmosis",
"AELOX", "AELOX",
"Dankin", "Dankin",
"Nicfit23", "Nicfit23",
"FloPro4Sho", "FloPro4Sho",
"Cristian Vazquez",
"wamekukyouzin", "wamekukyouzin",
"drum matthieu", "drum matthieu",
"Dogmaster", "Dogmaster",
"Matt Wenzel",
"Frank Nitty", "Frank Nitty",
"Magic Noob",
"Christopher Michel", "Christopher Michel",
"Serge Bekenkamp", "Serge Bekenkamp",
"DougPeterson",
"LeoZero", "LeoZero",
"Antonio Pontes", "Antonio Pontes",
"ApathyJones", "ApathyJones",
"Julian V", "Julian V",
"Steven Owens", "Steven Owens",
"nahinahi9", "nahinahi9",
"Kevin John Duck",
"Dustin Chen", "Dustin Chen",
"dan",
"Blackfish95", "Blackfish95",
"Mouthlessman", "Mouthlessman",
"Paul Kroll", "Paul Kroll",
"otaku fra",
"MiraiKuriyamaSy",
"Bas Imagineer", "Bas Imagineer",
"yuxz69", "yuxz69",
"Adam Taylor",
"Weird_With_A_Beard",
"esthe", "esthe",
"Pozadine1", "decoy",
"Qarob",
"AIGooner",
"Luc",
"ProtonPrince", "ProtonPrince",
"DiffDuck", "DiffDuck",
"elu3199", "elu3199",
@@ -217,46 +224,50 @@
"wundershark", "wundershark",
"mr_dinosaur", "mr_dinosaur",
"Tyrswood", "Tyrswood",
"Ray Wing",
"Ranzitho",
"Gus",
"MJG",
"linnfrey", "linnfrey",
"IamAyam", "IamAyam",
"skaterb949", "skaterb949",
"Josef Lanzl", "Josef Lanzl",
"Nerezza",
"confiscated Zyra", "confiscated Zyra",
"Error_Rule34_Not_found", "Error_Rule34_Not_found",
"aezin",
"jcay015",
"Gerald Welly", "Gerald Welly",
"Roslynd", "Erik Lopez",
"Mateo Curić",
"Tee Gee", "Tee Gee",
"Geolog", "Geolog",
"tarek helmi", "tarek helmi",
"Neco28", "Neco28",
"Eris3D",
"Max Marklund", "Max Marklund",
"David Ortega", "David Ortega",
"Cristian Vazquez",
"Magic Noob",
"Pronredn", "Pronredn",
"DougPeterson", "a _",
"Jeff", "Jeff",
"Bruce", "Bruce",
"lh qwe", "lh qwe",
"Kevin John Duck", "James Coleman",
"conner", "conner",
"Kevin Christopher", "Kevin Christopher",
"Chad Idk",
"dd", "dd",
"Princess Bright Eyes", "Princess Bright Eyes",
"Dušan Ryban", "Dušan Ryban",
"Felipe dos Santos", "Felipe dos Santos",
"sjon kreutz",
"John Statham", "John Statham",
"Douglas Gaspar", "Douglas Gaspar",
"Metryman55", "Metryman55",
"AlexDuKaNa", "AlexDuKaNa",
"George", "George",
"dw", "dw",
"decoy",
"Ray Wing",
"Ranzitho",
"Gus",
"地獄の禄", "地獄の禄",
"MJG",
"David LaVallee", "David LaVallee",
"ae", "ae",
"Tr4shP4nda", "Tr4shP4nda",
@@ -273,19 +284,20 @@
"몽타주", "몽타주",
"Kland", "Kland",
"Hailshem", "Hailshem",
"kudari",
"Naomi Hale Danchi",
"epicgamer0020690",
"Richard",
"奚明 刘", "奚明 刘",
"Andrew",
"Brian M", "Brian M",
"Nerezza", "Robert Wegemund",
"sanborondon", "sanborondon",
"준희 김", "준희 김",
"Taylor Funk", "Taylor Funk",
"aezin",
"Thought2Form", "Thought2Form",
"jcay015",
"Kevin Picco", "Kevin Picco",
"Erik Lopez", "Sadlip",
"Mateo Curić",
"Eris3D",
"Tomohiro Baba", "Tomohiro Baba",
"m", "m",
"Noora", "Noora",
@@ -294,32 +306,30 @@
"Mattssn", "Mattssn",
"Mikko Hemilä", "Mikko Hemilä",
"Jamie Ogletree", "Jamie Ogletree",
"a _", "Michael Taylor",
"James Coleman",
"Martial", "Martial",
"Emil Andersson", "Emil Andersson",
"Ouro Boros", "Ouro Boros",
"Chad Idk", "Atilla Berke Pekduyar",
"Steam Steam", "Steam Steam",
"CryptoTraderJK", "CryptoTraderJK",
"Decx _",
"Yuji Kaneko", "Yuji Kaneko",
"Davaitamin", "Davaitamin",
"Rops Alot", "Rops Alot",
"tedcor", "tedcor",
"Sam", "Sam",
"Fotek Design", "Fotek Design",
"sjon kreutz",
"Ace Ventura", "Ace Ventura",
"LarsesFPC",
"MadSpin", "MadSpin",
"inbijiburu", "inbijiburu",
"Nick “Loadstone” D", "Nick “Loadstone” D",
"momokai", "momokai",
"starbugx", "starbugx",
"kudari",
"Naomi Hale Danchi",
"dc7431", "dc7431",
"ken", "ken",
"epicgamer0020690", "Crocket",
"Joshua Porrata", "Joshua Porrata",
"keemun", "keemun",
"SuBu", "SuBu",
@@ -339,22 +349,24 @@
"KitKatM", "KitKatM",
"socrasteeze", "socrasteeze",
"OrganicArtifact", "OrganicArtifact",
"MudkipMedkitz",
"deanbrian",
"Alex Wortman",
"Cody",
"emadsultan",
"Vir", "Vir",
"gzmzmvp", "gzmzmvp",
"Richard",
"Andrew",
"Robert Wegemund",
"Littlehuggy", "Littlehuggy",
"Gregory Kozhemiak", "Gregory Kozhemiak",
"Draven T", "Draven T",
"mrjuan", "mrjuan",
"Brian Buie", "Brian Buie",
"Sadlip",
"Eric Whitney", "Eric Whitney",
"Joey Callahan", "Joey Callahan",
"Aquatic Coffee", "Aquatic Coffee",
"Ivan Tadic", "Ivan Tadic",
"Mike Simone", "Mike Simone",
"John J Linehan",
"ethanfel", "ethanfel",
"Elliot E", "Elliot E",
"Morgandel", "Morgandel",
@@ -366,34 +378,30 @@
"Sloan Steddy", "Sloan Steddy",
"Temikus", "Temikus",
"Artokun", "Artokun",
"Michael Taylor", "hexxish",
"Derek Baker", "Derek Baker",
"Anthony Faxlandez", "Anthony Faxlandez",
"battu", "battu",
"Michael Anthony Scott", "Michael Anthony Scott",
"Atilla Berke Pekduyar",
"Nathan", "Nathan",
"Decx _", "NICHOLAS BAXLEY",
"Pat Hen", "Pat Hen",
"Xeeosat",
"Ed Wang",
"Jordan Shaw", "Jordan Shaw",
"g unit",
"Srdb", "Srdb",
"四糸凜音", "四糸凜音",
"Nihongasuki", "Nihongasuki",
"LarsesFPC",
"JC", "JC",
"Prompt Pirate", "Prompt Pirate",
"uwutismxd", "uwutismxd",
"FrxzenSnxw", "FrxzenSnxw",
"zenobeus", "zenobeus",
"Crocket",
"Jackthemind",
"ryoma", "ryoma",
"Stryker", "Stryker",
"ResidentDeviant", "ResidentDeviant",
"MudkipMedkitz", "Ginnie",
"deanbrian",
"Alex Wortman",
"Cody",
"Raku", "Raku",
"smart.edge5178", "smart.edge5178",
"InformedViewz", "InformedViewz",
@@ -415,6 +423,15 @@
"SpringBootisTrash", "SpringBootisTrash",
"carsten", "carsten",
"ikok", "ikok",
"DarkRoast",
"letzte",
"Nasty+Hobbit",
"Sora+Yori",
"lrdchs2",
"Duk3+Rand0m",
"Nathen+Choi",
"T",
"cocona",
"ElitaSSJ4", "ElitaSSJ4",
"David Schenck", "David Schenck",
"Wolfe7D1", "Wolfe7D1",
@@ -426,7 +443,6 @@
"Goldwaters", "Goldwaters",
"Kauffy", "Kauffy",
"Zude", "Zude",
"John J Linehan",
"Kyler", "Kyler",
"Edward Kennedy", "Edward Kennedy",
"Justin Blaylock", "Justin Blaylock",
@@ -435,17 +451,14 @@
"Vane Holzer", "Vane Holzer",
"psytrax", "psytrax",
"Cyrus Fett", "Cyrus Fett",
"hexxish", "Xenon Xue",
"notedfakes", "notedfakes",
"Billy Gladky", "Billy Gladky",
"NICHOLAS BAXLEY",
"Michael Scott", "Michael Scott",
"Probis", "Probis",
"Ed Wang",
"Wes Sims", "Wes Sims",
"ItsGeneralButtNaked", "ItsGeneralButtNaked",
"Donor4115", "Donor4115",
"g unit",
"Distortik", "Distortik",
"Filippo Ferrari", "Filippo Ferrari",
"Youguang", "Youguang",
@@ -460,9 +473,14 @@
"Mitchell Robson", "Mitchell Robson",
"Whitepinetrader", "Whitepinetrader",
"POPPIN", "POPPIN",
"Ginnie",
"emadsultan",
"nanana", "nanana",
"ChaChanoKo",
"ghoulars",
"null",
"Beau",
"redcarrot",
"powerbot99",
"Fthehappy",
"g", "g",
"J", "J",
"Alan+Cano", "Alan+Cano",
@@ -474,15 +492,6 @@
"quantenmecha", "quantenmecha",
"Jason+Nash", "Jason+Nash",
"BillyBoy84", "BillyBoy84",
"DarkRoast",
"letzte",
"Nasty+Hobbit",
"Sora+Yori",
"lrdchs2",
"Duk3+Rand0m",
"Nathen+Choi",
"T",
"cocona",
"Buecyb99", "Buecyb99",
"Welkor", "Welkor",
"John Martin", "John Martin",
@@ -491,6 +500,8 @@
"moranqianlong", "moranqianlong",
"Kalli Core", "Kalli Core",
"Time Valentine", "Time Valentine",
"Christian Schäfer",
"りん あめ",
"Михал Михалыч", "Михал Михалыч",
"Matt", "Matt",
"Frogmilk", "Frogmilk",
@@ -501,21 +512,26 @@
"Anonym dkjglfleeoeldldldlkf", "Anonym dkjglfleeoeldldldlkf",
"Ezokewn", "Ezokewn",
"SendingRavens", "SendingRavens",
"Xenon Xue",
"JackJohnnyJim", "JackJohnnyJim",
"TenaciousD",
"Dmitry Ryzhov",
"Khánh Đặng",
"Edward Ten Eyck", "Edward Ten Eyck",
"Michael Docherty", "Michael Docherty",
"Jimmy Borup",
"Paul Hartsuyker", "Paul Hartsuyker",
"Henrique Faiolli",
"elitassj", "elitassj",
"Solixer", "Solixer",
"Pete Pain",
"Jacob Winter", "Jacob Winter",
"Ryan Presley Ng", "Ryan Presley Ng",
"jinksta187", "jinksta187",
"RHopkirk",
"Andrew Wilkinson", "Andrew Wilkinson",
"Manu Thetug", "Manu Thetug",
"Karlanx", "Karlanx",
"Lyavph", "Lyavph",
"Maxim",
"David", "David",
"Meilo", "Meilo",
"operationancut", "operationancut",
@@ -537,6 +553,17 @@
"Scott", "Scott",
"Muratoraccio", "Muratoraccio",
"D", "D",
"2turbo",
"Somebody",
"Balut+Omelette",
"Dmitry+Viznesenskiy",
"tanjin90",
"sternenkrieger",
"eriick",
"Patrick+Bryan",
"Pascalou",
"lighthawke",
"Lev+Lanevskiy",
"low9", "low9",
"Winged", "Winged",
"YassineKhaled", "YassineKhaled",
@@ -552,13 +579,6 @@
"Alex", "Alex",
"Jacky+Ho", "Jacky+Ho",
"Karru", "Karru",
"ghoulars",
"ChaChanoKo",
"null",
"Beau",
"redcarrot",
"powerbot99",
"Fthehappy",
"generic404", "generic404",
"abattoirblues", "abattoirblues",
"zounik", "zounik",
@@ -568,9 +588,10 @@
"Bob Barker", "Bob Barker",
"edk", "edk",
"Tú Nguyễn Lý Hoàng", "Tú Nguyễn Lý Hoàng",
"shira1011",
"Ben D",
"G",
"Ronan Delevacq", "Ronan Delevacq",
"Christian Schäfer",
"りん あめ",
"ja s", "ja s",
"Doug Mason", "Doug Mason",
"Jeremy Townsend", "Jeremy Townsend",
@@ -580,38 +601,41 @@
"Sean voets", "Sean voets",
"Owen Gwosdz", "Owen Gwosdz",
"Jarrid Lee", "Jarrid Lee",
"Poophead27 Blyat",
"Kor", "Kor",
"Joseph Hanson", "Joseph Hanson",
"John Rednoulf", "John Rednoulf",
"Spire",
"Boba Smith", "Boba Smith",
"Devil Lude", "Devil Lude",
"David Murcko", "David Murcko",
"MR.Bear", "MR.Bear",
"Jack Dole", "Jack Dole",
"somethingtosay8",
"ivistorm",
"max blo", "max blo",
"Sauv", "Sauv",
"Steven", "Steven",
"CptNeo", "CptNeo",
"TenaciousD",
"Dmitry Ryzhov",
"Khánh Đặng",
"Maso", "Maso",
"Ted Cart",
"Sage Himeros",
"Eric Ketchum", "Eric Ketchum",
"Kevin Wallace", "Kevin Wallace",
"Jimmy Borup", "David Spearing",
"ChicRic", "ChicRic",
"Tigon", "Tigon",
"BastardSama", "BastardSama",
"mercur", "mercur",
"Pete Pain", "Tania Nayelli Fernandez",
"RHopkirk", "Draconach",
"Yavizu3d", "Yavizu3d",
"Maxim",
"Yves Poezevara", "Yves Poezevara",
"Teriak47", "Teriak47",
"Just me", "Just me",
"Raf Stahelin", "Raf Stahelin",
"Вячеслав Маринин", "Вячеслав Маринин",
"Dkommander22",
"Cola Matthew", "Cola Matthew",
"OniNoKen", "OniNoKen",
"Iain Wisely", "Iain Wisely",
@@ -655,6 +679,17 @@
"SelfishMedic", "SelfishMedic",
"adderleighn", "adderleighn",
"EnragedAntelope", "EnragedAntelope",
"Monix",
"Trolinka",
"IshouI;_;",
"PredragR",
"Clauzmak",
"Nerick",
"JoL",
"Gold_miner_ego",
"SundayRage",
"YoruHime",
"matter",
"SRCRCOSS", "SRCRCOSS",
"imer", "imer",
"Akkas+Haque", "Akkas+Haque",
@@ -675,18 +710,8 @@
"Sildoren", "Sildoren",
"Darvidous", "Darvidous",
"Seon+Song", "Seon+Song",
"2turbo",
"balut+omelette",
"Nebuleux", "Nebuleux",
"Dmitry+Viznesenskiy",
"Tanjin90",
"Somebody",
"sternenkrieger",
"eriick",
"Join+Chun", "Join+Chun",
"Pascalou",
"lighthawke",
"Terraformer",
"GDS+DEV", "GDS+DEV",
"4rt+r3d", "4rt+r3d",
"you+halo9", "you+halo9",
@@ -712,17 +737,16 @@
"_ G3n", "_ G3n",
"Donovan Jenkins", "Donovan Jenkins",
"Hans Meier", "Hans Meier",
"shira1011",
"sicarius", "sicarius",
"Michael Eid", "Michael Eid",
"Wolf and Fox Legends",
"beersandbacon", "beersandbacon",
"Neko Desco", "Neko Desco",
"Bob barker", "Bob barker",
"Ben D",
"Ninja Tom", "Ninja Tom",
"G",
"karim ben brik", "karim ben brik",
"Vinarus", "Vinarus",
"Josh Snyder",
"Michael Zhu", "Michael Zhu",
"Nemisu", "Nemisu",
"Seraphy", "Seraphy",
@@ -732,41 +756,42 @@
"jumpd", "jumpd",
"John C", "John C",
"Rim", "Rim",
"Room Light",
"Jairus Knudsen", "Jairus Knudsen",
"Poophead27 Blyat",
"Xan Dionysus", "Xan Dionysus",
"Patryk Serious",
"Nathan lee", "Nathan lee",
"Lyle Liston", "lylepaul",
"Middo", "Middo",
"Forbidden Atelier", "Forbidden Atelier",
"Thomas Sankowski", "Thomas Sankowski",
"Spire",
"DrB", "DrB",
"AZ Party Oasis", "AZ Party Oasis",
"Adictedtohumping", "Adictedtohumping",
"Snorklebort",
"Towelie", "Towelie",
"TheFusion", "TheFusion",
"matt", "matt",
"dsffsdfsdfsdfsdfsdf", "dsffsdfsdfsdfsdfsdf",
"somethingtosay8",
"Jean-françois SEMA", "Jean-françois SEMA",
"3zS4QNQ4", "3zS4QNQ4",
"Terminuz", "Terminuz",
"Kurt", "Kurt",
"ivistorm",
"Matt M.", "Matt M.",
"Ivan Imes", "Ivan Imes",
"J M",
"Bouya shaka",
"Faburizu", "Faburizu",
"Jack Lawfield", "Jack Lawfield",
"jimyjomson", "jimyjomson",
"Borte", "Borte",
"JaeHyun Jang",
"Chase Kwon", "Chase Kwon",
"Ted Cart", "yyuvuvu",
"Sage Himeros",
"Inyoshu", "Inyoshu",
"Chad Barnes", "Chad Barnes",
"Person Y", "Person Y",
"David Spearing", "Nomki",
"James Ming", "James Ming",
"vanditking", "vanditking",
"kripitonga", "kripitonga",
@@ -787,5 +812,5 @@
"Somebody", "Somebody",
"CK" "CK"
], ],
"totalCount": 784 "totalCount": 809
} }

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "Stammverzeichnis", "modelRoot": "Stammverzeichnis",
"moreOptions": "Weitere Optionen",
"collapseAll": "Alle Ordner einklappen", "collapseAll": "Alle Ordner einklappen",
"pinSidebar": "Sidebar anheften", "pinSidebar": "Sidebar anheften",
"unpinSidebar": "Sidebar lösen", "unpinSidebar": "Sidebar lösen",
"hideOnThisPage": "Seitenleiste auf dieser Seite ausblenden",
"showSidebar": "Seitenleiste anzeigen",
"sidebarHiddenNotification": "Seitenleiste auf der Seite {page} ausgeblendet",
"switchToListView": "Zur Listenansicht wechseln", "switchToListView": "Zur Listenansicht wechseln",
"switchToTreeView": "Zur Baumansicht wechseln", "switchToTreeView": "Zur Baumansicht wechseln",
"recursiveOn": "Unterordner einbeziehen", "recursiveOn": "Unterordner einbeziehen",

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "Root", "modelRoot": "Root",
"moreOptions": "More options",
"collapseAll": "Collapse All Folders", "collapseAll": "Collapse All Folders",
"pinSidebar": "Pin Sidebar", "pinSidebar": "Pin Sidebar",
"unpinSidebar": "Unpin Sidebar", "unpinSidebar": "Unpin Sidebar",
"hideOnThisPage": "Hide sidebar on this page",
"showSidebar": "Show sidebar",
"sidebarHiddenNotification": "Folder sidebar hidden on {page} page",
"switchToListView": "Switch to List View", "switchToListView": "Switch to List View",
"switchToTreeView": "Switch to Tree View", "switchToTreeView": "Switch to Tree View",
"recursiveOn": "Include subfolders", "recursiveOn": "Include subfolders",

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "Raíz", "modelRoot": "Raíz",
"moreOptions": "Más opciones",
"collapseAll": "Colapsar todas las carpetas", "collapseAll": "Colapsar todas las carpetas",
"pinSidebar": "Fijar barra lateral", "pinSidebar": "Fijar barra lateral",
"unpinSidebar": "Desfijar barra lateral", "unpinSidebar": "Desfijar barra lateral",
"hideOnThisPage": "Ocultar barra lateral en esta página",
"showSidebar": "Mostrar barra lateral",
"sidebarHiddenNotification": "Barra lateral oculta en la página {page}",
"switchToListView": "Cambiar a vista de lista", "switchToListView": "Cambiar a vista de lista",
"switchToTreeView": "Cambiar a vista de árbol", "switchToTreeView": "Cambiar a vista de árbol",
"recursiveOn": "Incluir subcarpetas", "recursiveOn": "Incluir subcarpetas",

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "Racine", "modelRoot": "Racine",
"moreOptions": "Plus d'options",
"collapseAll": "Réduire tous les dossiers", "collapseAll": "Réduire tous les dossiers",
"pinSidebar": "Épingler la barre latérale", "pinSidebar": "Épingler la barre latérale",
"unpinSidebar": "Désépingler la barre latérale", "unpinSidebar": "Désépingler la barre latérale",
"hideOnThisPage": "Masquer la barre latérale sur cette page",
"showSidebar": "Afficher la barre latérale",
"sidebarHiddenNotification": "Barre latérale masquée sur la page {page}",
"switchToListView": "Passer en vue liste", "switchToListView": "Passer en vue liste",
"switchToTreeView": "Passer en vue arborescence", "switchToTreeView": "Passer en vue arborescence",
"recursiveOn": "Inclure les sous-dossiers", "recursiveOn": "Inclure les sous-dossiers",

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "שורש", "modelRoot": "שורש",
"moreOptions": "אפשרויות נוספות",
"collapseAll": "כווץ את כל התיקיות", "collapseAll": "כווץ את כל התיקיות",
"pinSidebar": "נעל סרגל צד", "pinSidebar": "נעל סרגל צד",
"unpinSidebar": "שחרר סרגל צד", "unpinSidebar": "שחרר סרגל צד",
"hideOnThisPage": "הסתר סרגל צד בדף זה",
"showSidebar": "הצג סרגל צד",
"sidebarHiddenNotification": "סרגל הצד מוסתר בדף {page}",
"switchToListView": "עבור לתצוגת רשימה", "switchToListView": "עבור לתצוגת רשימה",
"switchToTreeView": "תצוגת עץ", "switchToTreeView": "תצוגת עץ",
"recursiveOn": "כלול תיקיות משנה", "recursiveOn": "כלול תיקיות משנה",

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "ルート", "modelRoot": "ルート",
"moreOptions": "その他のオプション",
"collapseAll": "すべてのフォルダを折りたたむ", "collapseAll": "すべてのフォルダを折りたたむ",
"pinSidebar": "サイドバーを固定", "pinSidebar": "サイドバーを固定",
"unpinSidebar": "サイドバーの固定を解除", "unpinSidebar": "サイドバーの固定を解除",
"hideOnThisPage": "このページでサイドバーを非表示",
"showSidebar": "サイドバーを表示",
"sidebarHiddenNotification": "{page}ページでサイドバーが非表示になっています",
"switchToListView": "リストビューに切り替え", "switchToListView": "リストビューに切り替え",
"switchToTreeView": "ツリー表示に切り替え", "switchToTreeView": "ツリー表示に切り替え",
"recursiveOn": "サブフォルダーを含める", "recursiveOn": "サブフォルダーを含める",

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "루트", "modelRoot": "루트",
"moreOptions": "더 많은 옵션",
"collapseAll": "모든 폴더 접기", "collapseAll": "모든 폴더 접기",
"pinSidebar": "사이드바 고정", "pinSidebar": "사이드바 고정",
"unpinSidebar": "사이드바 고정 해제", "unpinSidebar": "사이드바 고정 해제",
"hideOnThisPage": "이 페이지에서 사이드바 숨기기",
"showSidebar": "사이드바 표시",
"sidebarHiddenNotification": "{page} 페이지에서 사이드바가 숨겨져 있습니다",
"switchToListView": "목록 보기로 전환", "switchToListView": "목록 보기로 전환",
"switchToTreeView": "트리 보기로 전환", "switchToTreeView": "트리 보기로 전환",
"recursiveOn": "하위 폴더 포함", "recursiveOn": "하위 폴더 포함",

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "Корень", "modelRoot": "Корень",
"moreOptions": "Дополнительные параметры",
"collapseAll": "Свернуть все папки", "collapseAll": "Свернуть все папки",
"pinSidebar": "Закрепить боковую панель", "pinSidebar": "Закрепить боковую панель",
"unpinSidebar": "Открепить боковую панель", "unpinSidebar": "Открепить боковую панель",
"hideOnThisPage": "Скрыть боковую панель на этой странице",
"showSidebar": "Показать боковую панель",
"sidebarHiddenNotification": "Боковая панель скрыта на странице {page}",
"switchToListView": "Переключить на вид списка", "switchToListView": "Переключить на вид списка",
"switchToTreeView": "Переключить на древовидный вид", "switchToTreeView": "Переключить на древовидный вид",
"recursiveOn": "Включать вложенные папки", "recursiveOn": "Включать вложенные папки",

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "根目录", "modelRoot": "根目录",
"moreOptions": "更多选项",
"collapseAll": "折叠所有文件夹", "collapseAll": "折叠所有文件夹",
"pinSidebar": "固定侧边栏", "pinSidebar": "固定侧边栏",
"unpinSidebar": "取消固定侧边栏", "unpinSidebar": "取消固定侧边栏",
"hideOnThisPage": "隐藏此页面侧边栏",
"showSidebar": "显示侧边栏",
"sidebarHiddenNotification": "{page}页面的文件夹侧边栏已隐藏",
"switchToListView": "切换到列表视图", "switchToListView": "切换到列表视图",
"switchToTreeView": "切换到树状视图", "switchToTreeView": "切换到树状视图",
"recursiveOn": "包含子文件夹", "recursiveOn": "包含子文件夹",

View File

@@ -953,9 +953,13 @@
}, },
"sidebar": { "sidebar": {
"modelRoot": "根目錄", "modelRoot": "根目錄",
"moreOptions": "更多選項",
"collapseAll": "全部摺疊資料夾", "collapseAll": "全部摺疊資料夾",
"pinSidebar": "固定側邊欄", "pinSidebar": "固定側邊欄",
"unpinSidebar": "取消固定側邊欄", "unpinSidebar": "取消固定側邊欄",
"hideOnThisPage": "隱藏此頁面側邊欄",
"showSidebar": "顯示側邊欄",
"sidebarHiddenNotification": "{page}頁面的資料夾側邊欄已隱藏",
"switchToListView": "切換至列表檢視", "switchToListView": "切換至列表檢視",
"switchToTreeView": "切換到樹狀檢視", "switchToTreeView": "切換到樹狀檢視",
"recursiveOn": "包含子資料夾", "recursiveOn": "包含子資料夾",

View File

@@ -129,6 +129,18 @@ class RecipePersistenceService:
if nsfw_level is not None and isinstance(nsfw_level, int): if nsfw_level is not None and isinstance(nsfw_level, int):
recipe_data["preview_nsfw_level"] = nsfw_level recipe_data["preview_nsfw_level"] = nsfw_level
# Compute recipe folder relative to recipes root, mirroring
# RecipeScanner._calculate_folder() which is only called during scan/load.
if recipe_scanner.recipes_dir:
recipe_file_dir = os.path.dirname(normalized_image_path)
try:
relative_folder = os.path.relpath(recipe_file_dir, recipe_scanner.recipes_dir)
if relative_folder in (".", ""):
relative_folder = ""
recipe_data["folder"] = relative_folder.replace(os.path.sep, "/")
except Exception:
recipe_data["folder"] = ""
json_filename = f"{recipe_id}.recipe.json" json_filename = f"{recipe_id}.recipe.json"
json_path = os.path.join(recipes_dir, json_filename) json_path = os.path.join(recipes_dir, json_filename)
json_path = os.path.normpath(json_path) json_path = os.path.normpath(json_path)

View File

@@ -1,7 +1,7 @@
[project] [project]
name = "comfyui-lora-manager" name = "comfyui-lora-manager"
description = "Revolutionize your workflow with the ultimate LoRA companion for ComfyUI!" description = "Revolutionize your workflow with the ultimate LoRA companion for ComfyUI!"
version = "1.0.11" version = "1.1.0"
license = {file = "LICENSE"} license = {file = "LICENSE"}
dependencies = [ dependencies = [
"aiohttp", "aiohttp",

View File

@@ -84,6 +84,7 @@
border-bottom: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color);
cursor: pointer; cursor: pointer;
transition: var(--transition-base); transition: var(--transition-base);
position: relative;
} }
.sidebar-header:hover { .sidebar-header:hover {
@@ -150,6 +151,120 @@
display: none; display: none;
} }
/* ===== Sidebar More Options Dropdown ===== */
.sidebar-more-dropdown {
position: absolute;
top: 100%;
right: 8px;
min-width: 190px;
background: var(--bg-color);
border: 1px solid var(--border-color);
border-radius: var(--border-radius-xs);
box-shadow: var(--shadow-lg);
z-index: calc(var(--z-overlay) + 20);
display: none;
overflow: hidden;
margin-top: 2px;
}
.sidebar-more-dropdown.open {
display: block;
animation: dropdownFadeIn 0.15s ease;
}
@keyframes dropdownFadeIn {
from { opacity: 0; transform: translateY(-4px); }
to { opacity: 1; transform: translateY(0); }
}
.sidebar-dropdown-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
cursor: pointer;
font-size: 0.85em;
color: var(--text-color);
transition: var(--transition-base);
white-space: nowrap;
}
.sidebar-dropdown-item:hover {
background: var(--lora-surface);
}
.sidebar-dropdown-item i {
width: 16px;
text-align: center;
color: var(--text-muted);
font-size: 0.9em;
flex-shrink: 0;
}
.sidebar-dropdown-item:hover i {
color: var(--text-color);
}
.sidebar-dropdown-item.disabled {
opacity: 0.4;
pointer-events: none;
}
/* ===== Sidebar Hidden Indicator (left edge) ===== */
.sidebar-hidden-indicator {
position: fixed;
left: 0;
top: 50%;
transform: translateY(-50%);
z-index: var(--z-overlay);
width: 14px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
background: var(--border-color);
opacity: 0.3;
border-radius: 0 4px 4px 0;
cursor: pointer;
transition: opacity 0.15s ease, background 0.15s ease;
}
.sidebar-hidden-indicator:hover {
opacity: 0.7;
background: var(--lora-accent);
}
.sidebar-hidden-indicator i {
font-size: 9px;
color: var(--text-muted);
transition: color 0.15s ease;
}
.sidebar-hidden-indicator:hover i {
color: white;
}
.sidebar-hidden-indicator-tooltip {
position: absolute;
left: 100%;
top: 50%;
transform: translateY(-50%);
margin-left: 8px;
padding: 4px 10px;
background: var(--text-color);
color: var(--bg-color);
font-size: 0.8em;
border-radius: 4px;
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s ease;
}
.sidebar-hidden-indicator:hover .sidebar-hidden-indicator-tooltip {
opacity: 1;
}
.sidebar-content { .sidebar-content {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;

View File

@@ -36,6 +36,8 @@ export class SidebarManager {
this.currentDropTarget = null; this.currentDropTarget = null;
this.lastPageControls = null; this.lastPageControls = null;
this.isDisabledBySetting = false; this.isDisabledBySetting = false;
this.isDisabledByPage = false;
this.isMoreDropdownOpen = false;
this.initializationPromise = null; this.initializationPromise = null;
this.isCreatingFolder = false; this.isCreatingFolder = false;
this._pendingDragState = null; // 用于保存拖拽创建文件夹时的状态 this._pendingDragState = null; // 用于保存拖拽创建文件夹时的状态
@@ -68,6 +70,10 @@ export class SidebarManager {
this.handleSidebarDrop = this.handleSidebarDrop.bind(this); this.handleSidebarDrop = this.handleSidebarDrop.bind(this);
this.handleCreateFolderSubmit = this.handleCreateFolderSubmit.bind(this); this.handleCreateFolderSubmit = this.handleCreateFolderSubmit.bind(this);
this.handleCreateFolderCancel = this.handleCreateFolderCancel.bind(this); this.handleCreateFolderCancel = this.handleCreateFolderCancel.bind(this);
this.handleMoreToggle = this.handleMoreToggle.bind(this);
this.handleMoreDropdownItemClick = this.handleMoreDropdownItemClick.bind(this);
this.handleDocumentClickForMore = this.handleDocumentClickForMore.bind(this);
this.getPageDisplayName = this.getPageDisplayName.bind(this);
} }
setHostPageControls(pageControls) { setHostPageControls(pageControls) {
@@ -100,6 +106,8 @@ export class SidebarManager {
this.initializeDragAndDrop(); this.initializeDragAndDrop();
this.updateSidebarTitle(); this.updateSidebarTitle();
this.restoreSidebarState(); this.restoreSidebarState();
// Re-apply DOM visibility now that per-page state is known
this.updateDomVisibility(!this.isDisabledBySetting);
await this.loadFolderTree(); await this.loadFolderTree();
if (this.isDisabledBySetting && !forceInitialize) { if (this.isDisabledBySetting && !forceInitialize) {
this.cleanup(); this.cleanup();
@@ -143,6 +151,13 @@ export class SidebarManager {
this.sidebarDragHandlersInitialized = false; this.sidebarDragHandlersInitialized = false;
} }
const moreDropdown = document.getElementById('sidebarMoreDropdown');
if (moreDropdown) {
moreDropdown.classList.remove('open');
}
this.isMoreDropdownOpen = false;
this.hideSidebarHiddenIndicator();
// Reset state // Reset state
this.pageControls = null; this.pageControls = null;
this.pageType = null; this.pageType = null;
@@ -151,6 +166,7 @@ export class SidebarManager {
this.expandedNodes = new Set(); this.expandedNodes = new Set();
this.openDropdown = null; this.openDropdown = null;
this.isHovering = false; this.isHovering = false;
this.isDisabledByPage = false;
this.apiClient = null; this.apiClient = null;
this.isInitialized = false; this.isInitialized = false;
this.recursiveSearchEnabled = true; this.recursiveSearchEnabled = true;
@@ -217,6 +233,18 @@ export class SidebarManager {
if (recursiveToggleBtn) { if (recursiveToggleBtn) {
recursiveToggleBtn.removeEventListener('click', this.handleRecursiveToggle); recursiveToggleBtn.removeEventListener('click', this.handleRecursiveToggle);
} }
const moreToggle = document.getElementById('sidebarMoreToggle');
if (moreToggle) {
moreToggle.removeEventListener('click', this.handleMoreToggle);
}
const moreDropdown = document.getElementById('sidebarMoreDropdown');
if (moreDropdown) {
moreDropdown.removeEventListener('click', this.handleMoreDropdownItemClick);
}
document.removeEventListener('click', this.handleDocumentClickForMore);
} }
initializeDragAndDrop() { initializeDragAndDrop() {
@@ -1045,6 +1073,19 @@ export class SidebarManager {
} }
}); });
} }
// More options dropdown
const moreToggle = document.getElementById('sidebarMoreToggle');
if (moreToggle) {
moreToggle.addEventListener('click', this.handleMoreToggle);
}
const moreDropdown = document.getElementById('sidebarMoreDropdown');
if (moreDropdown) {
moreDropdown.addEventListener('click', this.handleMoreDropdownItemClick);
}
document.addEventListener('click', this.handleDocumentClickForMore);
} }
handleDocumentClick(event) { handleDocumentClick(event) {
@@ -1066,6 +1107,7 @@ export class SidebarManager {
this.isPinned = !this.isPinned; this.isPinned = !this.isPinned;
this.updateAutoHideState(); this.updateAutoHideState();
this.updatePinButton(); this.updatePinButton();
this.updateMoreDropdownLabels();
this.saveSidebarState(); this.saveSidebarState();
this.updateContainerMargin(); this.updateContainerMargin();
} }
@@ -1129,7 +1171,7 @@ export class SidebarManager {
} }
updateAutoHideState() { updateAutoHideState() {
if (this.isDisabledBySetting) return; if (this.isDisabledBySetting || this.isDisabledByPage) return;
const sidebar = document.getElementById('folderSidebar'); const sidebar = document.getElementById('folderSidebar');
const hoverArea = document.getElementById('sidebarHoverArea'); const hoverArea = document.getElementById('sidebarHoverArea');
@@ -1174,9 +1216,12 @@ export class SidebarManager {
if (!container || !sidebar || this.isDisabledBySetting) return; if (!container || !sidebar || this.isDisabledBySetting) return;
// Reset margin to default // Always reset margin first — needed when transitioning from visible to hidden
container.style.marginLeft = ''; container.style.marginLeft = '';
// When per-page disabled, skip adjustment but margin is already reset
if (this.isDisabledByPage) return;
// Only adjust margin if sidebar is visible and pinned // Only adjust margin if sidebar is visible and pinned
if ((this.isPinned || this.isHovering) && this.isVisible) { if ((this.isPinned || this.isHovering) && this.isVisible) {
const sidebarWidth = sidebar.offsetWidth; const sidebarWidth = sidebar.offsetWidth;
@@ -1193,20 +1238,29 @@ export class SidebarManager {
} }
updateDomVisibility(enabled) { updateDomVisibility(enabled) {
// Per-page disable adds on top of global setting
const isVisible = enabled && !this.isDisabledByPage;
const sidebar = document.getElementById('folderSidebar'); const sidebar = document.getElementById('folderSidebar');
const hoverArea = document.getElementById('sidebarHoverArea'); const hoverArea = document.getElementById('sidebarHoverArea');
if (sidebar) { if (sidebar) {
sidebar.classList.toggle('hidden-by-setting', !enabled); sidebar.classList.toggle('hidden-by-setting', !isVisible);
sidebar.setAttribute('aria-hidden', (!enabled).toString()); sidebar.setAttribute('aria-hidden', (!isVisible).toString());
} }
if (hoverArea) { if (hoverArea) {
hoverArea.classList.toggle('hidden-by-setting', !enabled); hoverArea.classList.toggle('hidden-by-setting', !isVisible);
if (!enabled) { if (!isVisible) {
hoverArea.classList.add('disabled'); hoverArea.classList.add('disabled');
} }
} }
// Show or hide the "sidebar hidden" notification
if (enabled && this.isDisabledByPage) {
this.showSidebarHiddenIndicator();
} else {
this.hideSidebarHiddenIndicator();
}
} }
async setSidebarEnabled(enabled) { async setSidebarEnabled(enabled) {
@@ -1266,6 +1320,133 @@ export class SidebarManager {
} }
} }
// ===== More Options Dropdown =====
handleMoreToggle(event) {
event.stopPropagation();
const dropdown = document.getElementById('sidebarMoreDropdown');
if (!dropdown) return;
this.isMoreDropdownOpen = !dropdown.classList.contains('open');
dropdown.classList.toggle('open', this.isMoreDropdownOpen);
this.updateMoreDropdownLabels();
}
handleMoreDropdownItemClick(event) {
const item = event.target.closest('.sidebar-dropdown-item');
if (!item) return;
const action = item.dataset.action;
if (!action) return;
const dropdown = document.getElementById('sidebarMoreDropdown');
if (dropdown) {
dropdown.classList.remove('open');
this.isMoreDropdownOpen = false;
}
switch (action) {
case 'toggle-pin':
this.handlePinToggle(event);
break;
case 'toggle-hide':
this.toggleHideOnThisPage();
break;
}
}
handleDocumentClickForMore(event) {
const dropdown = document.getElementById('sidebarMoreDropdown');
const toggle = document.getElementById('sidebarMoreToggle');
if (!dropdown || !toggle) return;
if (!dropdown.contains(event.target) && !toggle.contains(event.target)) {
dropdown.classList.remove('open');
this.isMoreDropdownOpen = false;
}
}
updateMoreDropdownLabels() {
const pinLabel = document.getElementById('sidebarMorePinLabel');
if (pinLabel) {
pinLabel.textContent = this.isPinned
? translate('sidebar.unpinSidebar')
: translate('sidebar.pinSidebar');
}
const hideItem = document.querySelector('.sidebar-dropdown-item[data-action="toggle-hide"]');
if (hideItem) {
const hideIcon = hideItem.querySelector('i');
const hideLabel = hideItem.querySelector('span');
if (this.isDisabledByPage) {
hideLabel.textContent = translate('sidebar.showSidebar');
if (hideIcon) {
hideIcon.className = 'fas fa-eye';
}
} else {
hideLabel.textContent = translate('sidebar.hideOnThisPage');
if (hideIcon) {
hideIcon.className = 'fas fa-eye-slash';
}
}
}
}
toggleHideOnThisPage() {
this.isDisabledByPage = !this.isDisabledByPage;
setStorageItem(`${this.pageType}_sidebarDisabled`, this.isDisabledByPage);
this.updateDomVisibility(!this.isDisabledBySetting);
this.updateAutoHideState();
this.updateContainerMargin();
this.updateMoreDropdownLabels();
if (!this.isDisabledByPage) {
this.hideSidebarHiddenIndicator();
} else {
showToast(
'sidebar.sidebarHiddenNotification',
{ page: this.getPageDisplayName() },
'info',
`Sidebar hidden on ${this.getPageDisplayName()} page`
);
}
}
getPageDisplayName() {
const names = {
loras: 'LoRAs',
recipes: 'Recipes',
checkpoints: 'Checkpoints',
embeddings: 'Embeddings',
};
return names[this.pageType] || this.pageType;
}
showSidebarHiddenIndicator() {
if (document.getElementById('sidebarHiddenIndicator')) return;
const indicator = document.createElement('div');
indicator.id = 'sidebarHiddenIndicator';
indicator.className = 'sidebar-hidden-indicator';
indicator.innerHTML = `
<i class="fas fa-chevron-right"></i>
<span class="sidebar-hidden-indicator-tooltip">${translate('sidebar.showSidebar')}</span>
`;
indicator.addEventListener('click', () => {
this.toggleHideOnThisPage();
});
document.body.appendChild(indicator);
}
hideSidebarHiddenIndicator() {
const indicator = document.getElementById('sidebarHiddenIndicator');
if (indicator) {
indicator.remove();
}
}
async loadFolderTree() { async loadFolderTree() {
try { try {
if (this.displayMode === 'tree') { if (this.displayMode === 'tree') {
@@ -1911,6 +2092,7 @@ export class SidebarManager {
const expandedPaths = getStorageItem(`${this.pageType}_expandedNodes`, []); const expandedPaths = getStorageItem(`${this.pageType}_expandedNodes`, []);
const displayMode = getStorageItem(`${this.pageType}_displayMode`, 'tree'); // 'tree' or 'list', default to 'tree' const displayMode = getStorageItem(`${this.pageType}_displayMode`, 'tree'); // 'tree' or 'list', default to 'tree'
const recursiveSearchEnabled = getStorageItem(`${this.pageType}_recursiveSearch`, true); const recursiveSearchEnabled = getStorageItem(`${this.pageType}_recursiveSearch`, true);
this.isDisabledByPage = getStorageItem(`${this.pageType}_sidebarDisabled`, false);
this.isPinned = isPinned; this.isPinned = isPinned;
this.expandedNodes = new Set(expandedPaths); this.expandedNodes = new Set(expandedPaths);

View File

@@ -18,6 +18,20 @@
<button class="sidebar-action-btn" id="sidebarPinToggle" title="{{ t('sidebar.unpinSidebar') }}"> <button class="sidebar-action-btn" id="sidebarPinToggle" title="{{ t('sidebar.unpinSidebar') }}">
<i class="fas fa-thumbtack"></i> <i class="fas fa-thumbtack"></i>
</button> </button>
<button class="sidebar-action-btn" id="sidebarMoreToggle" title="{{ t('sidebar.moreOptions') }}">
<i class="fas fa-ellipsis-v"></i>
</button>
</div>
<!-- Dropdown menu for more options -->
<div class="sidebar-more-dropdown" id="sidebarMoreDropdown">
<div class="sidebar-dropdown-item" data-action="toggle-pin">
<i class="fas fa-thumbtack"></i>
<span id="sidebarMorePinLabel">{{ t('sidebar.pinSidebar') }}</span>
</div>
<div class="sidebar-dropdown-item" data-action="toggle-hide">
<i class="fas fa-eye-slash"></i>
<span>{{ t('sidebar.hideOnThisPage') }}</span>
</div>
</div> </div>
</div> </div>
<div class="sidebar-content"> <div class="sidebar-content">