mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
refactor: move supporters loading to separate API endpoint
- Add SupportersHandler in misc_handlers.py to serve /api/lm/supporters - Register new endpoint in misc_route_registrar.py - Remove supporters from page load template context in model_handlers.py - Create supportersService.js for frontend data fetching - Update Header.js to fetch supporters when support modal opens - Modify support_modal.html to use client-side rendering This change improves page load performance by loading supporters data on-demand instead of during initial page render.
This commit is contained in:
621
data/supporters.json
Normal file
621
data/supporters.json
Normal file
@@ -0,0 +1,621 @@
|
||||
{
|
||||
"specialThanks": [
|
||||
"dispenser",
|
||||
"EbonEagle",
|
||||
"DanielMagPizza",
|
||||
"Scott R"
|
||||
],
|
||||
"allSupporters": [
|
||||
"megakirbs",
|
||||
"Brennok",
|
||||
"Christian Byrne",
|
||||
"wackop",
|
||||
"Insomnia Art Designs",
|
||||
"2018cfh",
|
||||
"Takkan",
|
||||
"$MetaSamsara",
|
||||
"onesecondinosaur",
|
||||
"stone9k",
|
||||
"Francisco Tatis",
|
||||
"FreelancerZ",
|
||||
"Gooohokrbe",
|
||||
"JongWon Han",
|
||||
"OldBones",
|
||||
"Rosenthal",
|
||||
"runte3221",
|
||||
"Birdy",
|
||||
"Fraser Cross",
|
||||
"Polymorphic Indeterminate",
|
||||
"Marc Whiffen",
|
||||
"Kiba",
|
||||
"Jorge Hussni",
|
||||
"Reno Lam",
|
||||
"Skalabananen",
|
||||
"esthe",
|
||||
"sig",
|
||||
"DM",
|
||||
"Sen314",
|
||||
"Estragon",
|
||||
"J\\B/ 8r0wns0n",
|
||||
"Andrew Wilson",
|
||||
"Buzzard",
|
||||
"carozzz",
|
||||
"ClockDaemon",
|
||||
"Cosmosis",
|
||||
"Echo",
|
||||
"Edgar Tejeda",
|
||||
"FloPro4Sho",
|
||||
"fnkylove",
|
||||
"Greybush",
|
||||
"iamresist",
|
||||
"Illrigger",
|
||||
"JackieWang",
|
||||
"James Dooley",
|
||||
"James Todd",
|
||||
"jmack",
|
||||
"Julian V",
|
||||
"KD",
|
||||
"lh qwe",
|
||||
"Lilleman",
|
||||
"Lisster",
|
||||
"Mark Corneglio",
|
||||
"Michael Wong",
|
||||
"Omnidex",
|
||||
"PM",
|
||||
"Release Cabrakan",
|
||||
"Ricky Carter",
|
||||
"Robert Stacey",
|
||||
"SarcasticHashtag",
|
||||
"SG",
|
||||
"Steven Owens",
|
||||
"tarek helmi",
|
||||
"Tee Gee",
|
||||
"Tim",
|
||||
"Tobi_Swagg",
|
||||
"Todd Keck",
|
||||
"Tom Corrigan",
|
||||
"VantAI",
|
||||
"Vik71it",
|
||||
"Wolffen",
|
||||
"Yushio",
|
||||
"zenbound",
|
||||
"itismyelement",
|
||||
"Mozzel",
|
||||
"Gingko Biloba",
|
||||
"Penfore",
|
||||
"BadassArabianMofo",
|
||||
"Liam MacDougal",
|
||||
"Sterilized",
|
||||
"Markus",
|
||||
"quarz",
|
||||
"Greg",
|
||||
"Douglas Gaspar",
|
||||
"JSST",
|
||||
"AlexDuKaNa",
|
||||
"Snaggwort",
|
||||
"George",
|
||||
"lmsupporter@fastmail.de",
|
||||
"Phil",
|
||||
"Carl G.",
|
||||
"Arlecchino Shion",
|
||||
"Charles Blakemore",
|
||||
"IamAyam",
|
||||
"wfpearl",
|
||||
"Rob Williams",
|
||||
"Aaron Bleuer",
|
||||
"Adam Shaw",
|
||||
"Alex",
|
||||
"Anthony Rizzo",
|
||||
"ASLPro3D",
|
||||
"Baekdoosixt",
|
||||
"bh",
|
||||
"Big Red",
|
||||
"Bishoujoker",
|
||||
"Briton Heilbrun",
|
||||
"confiscated Zyra",
|
||||
"conner",
|
||||
"contrite831",
|
||||
"corde",
|
||||
"Cory Paza",
|
||||
"CryptoTraderJK",
|
||||
"daniel dove",
|
||||
"David Ortega",
|
||||
"dl0901dm",
|
||||
"FinalyFree",
|
||||
"Graham Colehour",
|
||||
"Jack B Nimble",
|
||||
"Jacob Hoehler",
|
||||
"Johnny",
|
||||
"Jonathan Ross",
|
||||
"JW Sin",
|
||||
"LacesOut!",
|
||||
"Luc Job",
|
||||
"Lustre",
|
||||
"Marlon Daniels",
|
||||
"Melville Parrish",
|
||||
"Nazono_hito",
|
||||
"Nick Walker",
|
||||
"Philip Hempel",
|
||||
"Princess Bright Eyes",
|
||||
"RedrockVP",
|
||||
"Starkselle",
|
||||
"Steven Pfeiffer",
|
||||
"Tak",
|
||||
"Timmy",
|
||||
"Tomohiro Baba",
|
||||
"Tori",
|
||||
"Tyler Trebuchon",
|
||||
"Weasyl",
|
||||
"whudunit",
|
||||
"wildnut",
|
||||
"Yaboi",
|
||||
"Zach Gonser",
|
||||
"Davaitamin",
|
||||
"Felipe dos Santos",
|
||||
"Aleksander Wujczyk",
|
||||
"AM Kuro",
|
||||
"jean jahren",
|
||||
"tedcor",
|
||||
"Pascal Dahle",
|
||||
"S Sang",
|
||||
"MagnaInsomnia",
|
||||
"Akira_HentAI",
|
||||
"Karl P.",
|
||||
"Gordon Cole",
|
||||
"yuxz69",
|
||||
"MadSpin",
|
||||
"[anonymous]",
|
||||
"dw",
|
||||
"N/A",
|
||||
"The Spawn",
|
||||
"graysock",
|
||||
"Greenmoustache",
|
||||
"Gamalonia",
|
||||
"fancypants",
|
||||
"Vir",
|
||||
"aai",
|
||||
"AELOX",
|
||||
"Anthony Faxlandez",
|
||||
"ApathyJones",
|
||||
"Aquatic Coffee",
|
||||
"batblue",
|
||||
"carey6409",
|
||||
"Christopher Michel",
|
||||
"Damon Cunliffe",
|
||||
"dan",
|
||||
"Digital",
|
||||
"Dogmaster",
|
||||
"Draven T",
|
||||
"drum matthieu",
|
||||
"Dustin Chen",
|
||||
"ethanfel",
|
||||
"Focuschannel",
|
||||
"Gonzalo Andre Allendes Lopez",
|
||||
"JaxMax",
|
||||
"Jimmy Ledbetter",
|
||||
"John Saveas",
|
||||
"Jwk0205",
|
||||
"LeoZero",
|
||||
"Lex Song",
|
||||
"M Postkasse",
|
||||
"Matt Wenzel",
|
||||
"Mattssn",
|
||||
"Max Marklund",
|
||||
"Mouthlessman",
|
||||
"nahinahi9",
|
||||
"Nicfit23",
|
||||
"Noora",
|
||||
"Olive",
|
||||
"Serge Bekenkamp",
|
||||
"Seth Christensen",
|
||||
"Some Guy Named Barry",
|
||||
"Steam Steam",
|
||||
"takyamtom",
|
||||
"ViperC",
|
||||
"wamekukyouzin",
|
||||
"奚明 刘",
|
||||
"otaku fra",
|
||||
"AbstractAss",
|
||||
"semicolon drainpipe",
|
||||
"Ran C",
|
||||
"Thesharingbrother",
|
||||
"Fotek Design",
|
||||
"ResidentDeviant",
|
||||
"Adam Taylor",
|
||||
"JC",
|
||||
"Weird_With_A_Beard",
|
||||
"Prompt Pirate",
|
||||
"Pozadine1",
|
||||
"uwutismxd",
|
||||
"Qarob",
|
||||
"AIGooner",
|
||||
"inbijiburu",
|
||||
"decoy",
|
||||
"Luc",
|
||||
"ProtonPrince",
|
||||
"DiffDuck",
|
||||
"elu3199",
|
||||
"Nick “Loadstone” D",
|
||||
"Hasturkun",
|
||||
"Jon Sandman",
|
||||
"Ubivis",
|
||||
"zounic",
|
||||
"CloudValley",
|
||||
"linnfrey",
|
||||
"zenobeus",
|
||||
"Jackthemind",
|
||||
"Stryker",
|
||||
"Pkrsky",
|
||||
"raf8osz5",
|
||||
"Antonio Pontes",
|
||||
"aRtFuL_DodGeR",
|
||||
"Billy Gladky",
|
||||
"Blackfish95",
|
||||
"blikkies",
|
||||
"Bohemian Corporal",
|
||||
"Bro Xie",
|
||||
"Bruce",
|
||||
"CrimsonDX",
|
||||
"Cristian Vazquez",
|
||||
"Dan",
|
||||
"Dankin",
|
||||
"DarkSunset",
|
||||
"dd",
|
||||
"DougPeterson",
|
||||
"Error_Rule34_Not_found",
|
||||
"Frank Nitty",
|
||||
"Goldwaters",
|
||||
"Griffin Dahlberg",
|
||||
"jinxedx",
|
||||
"Joboshy",
|
||||
"Kevin Christopher",
|
||||
"Kevin John Duck",
|
||||
"Kyler",
|
||||
"Magic Noob",
|
||||
"Neco28",
|
||||
"Ouro Boros",
|
||||
"Paul Kroll",
|
||||
"Probis",
|
||||
"Roslynd",
|
||||
"Shock Shockor",
|
||||
"Spitfire_502",
|
||||
"X",
|
||||
"yer fey",
|
||||
"Zude",
|
||||
"太郎 ゲーム",
|
||||
"준희 김",
|
||||
"shrshpp",
|
||||
"ItsGeneralButtNaked",
|
||||
"John Statham",
|
||||
"Nimess",
|
||||
"Bas Imagineer",
|
||||
"Pat Hen",
|
||||
"Youguang",
|
||||
"andrewzpong",
|
||||
"FrxzenSnxw",
|
||||
"BossGame",
|
||||
"thesoftwaredruid",
|
||||
"wundershark",
|
||||
"mr_dinosaur",
|
||||
"Tyrswood",
|
||||
"Ray Wing",
|
||||
"Ranzitho",
|
||||
"Gus",
|
||||
"地獄の禄",
|
||||
"MJG",
|
||||
"David LaVallee",
|
||||
"ae",
|
||||
"Tr4shP4nda",
|
||||
"WRL_SPR",
|
||||
"capn",
|
||||
"Joseph",
|
||||
"anonymousoddity",
|
||||
"Mirko Katzula",
|
||||
"dan",
|
||||
"Piccio08",
|
||||
"kumakichi",
|
||||
"a _",
|
||||
"aezin",
|
||||
"battu",
|
||||
"Brian M",
|
||||
"Chad Idk",
|
||||
"Chris",
|
||||
"Emil Andersson",
|
||||
"Emil Bernhoff",
|
||||
"Erik Lopez",
|
||||
"Eris3D",
|
||||
"Geolog",
|
||||
"Gerald Welly",
|
||||
"Haru Yotu",
|
||||
"James Coleman",
|
||||
"Jamie Ogletree",
|
||||
"jcay015",
|
||||
"Jeff",
|
||||
"John Martin",
|
||||
"Josef Lanzl",
|
||||
"Kevin Picco",
|
||||
"m",
|
||||
"Martial",
|
||||
"Mateo Curić",
|
||||
"Matura Arbeit",
|
||||
"Michael Docherty",
|
||||
"moranqianlong",
|
||||
"Nerezza",
|
||||
"Pierce McBride",
|
||||
"sanborondon",
|
||||
"SendingRavens",
|
||||
"Taylor Funk",
|
||||
"TBitz33",
|
||||
"Thought2Form",
|
||||
"Yuji Kaneko",
|
||||
"elitassj4",
|
||||
"Dušan Ryban",
|
||||
"Jacob Winter",
|
||||
"Jordan Shaw",
|
||||
"Sam",
|
||||
"Rops Alot",
|
||||
"SRDB",
|
||||
"sjon kreutz",
|
||||
"g unit",
|
||||
"Ace Ventura",
|
||||
"David",
|
||||
"Meilo",
|
||||
"Nihongasuki",
|
||||
"Pen Bouryoung",
|
||||
"shinonomeiro",
|
||||
"Snille",
|
||||
"Metryman55",
|
||||
"MaartenAlbers",
|
||||
"khanh duy",
|
||||
"xybrightsummer",
|
||||
"ColdBread",
|
||||
"PhilW",
|
||||
"momokai",
|
||||
"cppbel",
|
||||
"starbugx",
|
||||
"Janik",
|
||||
"Moon Knight",
|
||||
"몽타주",
|
||||
"Kland",
|
||||
"Hailshem",
|
||||
"kudari",
|
||||
"Naomi Hale Danchi",
|
||||
"dc7431",
|
||||
"ken",
|
||||
"Inversity",
|
||||
"Crocket",
|
||||
"AIVORY3D",
|
||||
"epicgamer0020690",
|
||||
"Joshua Porrata",
|
||||
"Cruel",
|
||||
"keemun",
|
||||
"SuBu",
|
||||
"RedPIXel",
|
||||
"MRBlack",
|
||||
"Kevinj",
|
||||
"Wind",
|
||||
"Nexus",
|
||||
"Mitchell Robson",
|
||||
"Ramneek“Guy”Ashok",
|
||||
"squid_actually",
|
||||
"Nat_20",
|
||||
"Kiyoe",
|
||||
"Edward Weeks",
|
||||
"kyoumei",
|
||||
"RadStorm04",
|
||||
"JohnDoe42054",
|
||||
"BillyHill",
|
||||
"humptynutz",
|
||||
"emyth",
|
||||
"Kalnei",
|
||||
"ryoma7612",
|
||||
"ResidentDeviant",
|
||||
"Scott",
|
||||
"gzmzmvp",
|
||||
"Aeternyx",
|
||||
"ahoystan",
|
||||
"Andrew",
|
||||
"Artokun",
|
||||
"Atilla Berke Pekduyar",
|
||||
"Bob Barker",
|
||||
"Brian Buie",
|
||||
"Decx _",
|
||||
"Derek Baker",
|
||||
"Doug Mason",
|
||||
"Eric Whitney",
|
||||
"hayden",
|
||||
"Ivan Tadic",
|
||||
"ja s",
|
||||
"Jack Dole",
|
||||
"Jacob McDaniel",
|
||||
"Jeremy Townsend",
|
||||
"Joey Callahan",
|
||||
"Joshua Gray",
|
||||
"kevin stoddard",
|
||||
"Kevin Wallace",
|
||||
"Kyron Mahan",
|
||||
"Leland Saunders",
|
||||
"Littlehuggy",
|
||||
"Maso",
|
||||
"Matheus Couto",
|
||||
"Michael Anthony Scott",
|
||||
"Michael Taylor",
|
||||
"Mike Simone",
|
||||
"Mikko Hemilä",
|
||||
"Morgandel",
|
||||
"mrjuan",
|
||||
"Noah",
|
||||
"Owen Gwosdz",
|
||||
"Richard",
|
||||
"Robert Wegemund",
|
||||
"Sadlip",
|
||||
"Sean voets",
|
||||
"Sloan Steddy",
|
||||
"Temikus",
|
||||
"Thomas Wanner",
|
||||
"y2Rxy7FdXzWo",
|
||||
"YOU SINWOO",
|
||||
"Paul Hartsuyker",
|
||||
"ChicRic",
|
||||
"mercur2002",
|
||||
"J C",
|
||||
"Distortik",
|
||||
"Yves Poezevara",
|
||||
"Teriak47",
|
||||
"Just me",
|
||||
"Raf Stahelin",
|
||||
"Вячеслав Маринин",
|
||||
"Cola Matthew",
|
||||
"OniNoKen",
|
||||
"Iain Wisely",
|
||||
"Zertens",
|
||||
"NOHOW",
|
||||
"Apo",
|
||||
"nekotxt",
|
||||
"choowkee",
|
||||
"Clusters",
|
||||
"ibrahim",
|
||||
"Highlandrise",
|
||||
"philcoraz",
|
||||
"mztn11",
|
||||
"ImagineerNL",
|
||||
"MrAcrtosSursus",
|
||||
"al300680",
|
||||
"pixl",
|
||||
"Robin",
|
||||
"chahknoir@gmail.com",
|
||||
"Marcus thronico",
|
||||
"nd01",
|
||||
"keno94d",
|
||||
"James Melzer",
|
||||
"Bartleby",
|
||||
"Renvertere",
|
||||
"Rahuy",
|
||||
"Hermann003",
|
||||
"D",
|
||||
"Foolish",
|
||||
"RevyHiep",
|
||||
"Captain_Swag",
|
||||
"obkircher",
|
||||
"Tree Tagger",
|
||||
"gwyar",
|
||||
"Coeur de cochon",
|
||||
"D",
|
||||
"edgecase",
|
||||
"Neoxena",
|
||||
"mrmhalo",
|
||||
"michael.isaza1",
|
||||
"chriphost",
|
||||
"KitKatM",
|
||||
"socrasteeze",
|
||||
"dg",
|
||||
"Whitepinetrader",
|
||||
"Maarten Harms",
|
||||
"OrganicArtifact",
|
||||
"四糸凜音",
|
||||
"MudkipMedkitz",
|
||||
"Israel",
|
||||
"deanbrian",
|
||||
"POPPIN",
|
||||
"Muratoraccio",
|
||||
"SelfishMedic",
|
||||
"Ginnie",
|
||||
"Alex Wortman",
|
||||
"Cody",
|
||||
"adderleighn",
|
||||
"Raku",
|
||||
"smart.edge5178",
|
||||
"emadsultan",
|
||||
"InformedViewz",
|
||||
"CHKeeho80",
|
||||
"Bubbafett",
|
||||
"leaf",
|
||||
"Menard",
|
||||
"Skyfire83",
|
||||
"Adam Rinehart",
|
||||
"D",
|
||||
"Pitpe11",
|
||||
"TheD1rtyD03",
|
||||
"EnragedAntelope",
|
||||
"moonpetal",
|
||||
"SomeDude",
|
||||
"g9p0o",
|
||||
"nanana",
|
||||
"TheHolySheep",
|
||||
"Monte Won",
|
||||
"SpringBootisTrash",
|
||||
"carsten",
|
||||
"ikok",
|
||||
"_ G3n",
|
||||
"ACTUALLY_the_Real_Willem_Dafoe",
|
||||
"Adictedtohumping",
|
||||
"AllTimeNoobie",
|
||||
"Banana Joe",
|
||||
"beersandbacon",
|
||||
"Chad Barnes",
|
||||
"Chase Kwon",
|
||||
"CptNeo",
|
||||
"Devil Lude",
|
||||
"Dismem",
|
||||
"Donovan Jenkins",
|
||||
"edk",
|
||||
"Edward Kennedy",
|
||||
"elleshar666",
|
||||
"Elliot E",
|
||||
"EpicElric",
|
||||
"Eric Ketchum",
|
||||
"Ezokewn",
|
||||
"Forbidden Atelier",
|
||||
"giani kidd",
|
||||
"gonzalo",
|
||||
"Goober719",
|
||||
"Gregory Kozhemiak",
|
||||
"han b",
|
||||
"hexxish",
|
||||
"Ink Temptation",
|
||||
"Invis",
|
||||
"james",
|
||||
"Jean-françois SEMA",
|
||||
"John C",
|
||||
"John J Linehan",
|
||||
"jumpd",
|
||||
"Justin Blaylock",
|
||||
"Justin Houston",
|
||||
"Kalli Core",
|
||||
"Kauffy",
|
||||
"Kurt",
|
||||
"Maximilian Pyko",
|
||||
"Mewtora",
|
||||
"Michael Eid",
|
||||
"Michael Scott",
|
||||
"Michael Zhu",
|
||||
"Middo",
|
||||
"Nathan",
|
||||
"Nathan lee",
|
||||
"NICHOLAS BAXLEY",
|
||||
"Nico",
|
||||
"notedfakes",
|
||||
"OrochiNights",
|
||||
"psytrax",
|
||||
"Rim",
|
||||
"Seraphy",
|
||||
"Theerat Jiramate",
|
||||
"Towelie",
|
||||
"Vane Holzer",
|
||||
"Wolfe7D1",
|
||||
"Xan Dionysus",
|
||||
"雨の心 落",
|
||||
"James Ming",
|
||||
"vanditking",
|
||||
"kripitonga",
|
||||
"Rizzi",
|
||||
"nimin",
|
||||
"OMAR LUCIANO",
|
||||
"BrentBertram",
|
||||
"eumelzocker",
|
||||
"dxjaymz",
|
||||
"L C",
|
||||
"Dude"
|
||||
],
|
||||
"totalCount": 614
|
||||
}
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "WeChat QR-Code anzeigen",
|
||||
"hideWechatQR": "WeChat QR-Code ausblenden"
|
||||
},
|
||||
"footer": "Vielen Dank, dass Sie LoRA Manager verwenden! ❤️"
|
||||
"footer": "Vielen Dank, dass Sie LoRA Manager verwenden! ❤️",
|
||||
"supporters": {
|
||||
"title": "Danke an alle Unterstützer",
|
||||
"subtitle": "Danke an {count} Unterstützer, die dieses Projekt möglich gemacht haben",
|
||||
"specialThanks": "Besonderer Dank",
|
||||
"allSupporters": "Alle Unterstützer",
|
||||
"totalCount": "{count} Unterstützer insgesamt"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "Show WeChat QR Code",
|
||||
"hideWechatQR": "Hide WeChat QR Code"
|
||||
},
|
||||
"footer": "Thank you for using LoRA Manager! ❤️"
|
||||
"footer": "Thank you for using LoRA Manager! ❤️",
|
||||
"supporters": {
|
||||
"title": "Thank You To Our Supporters",
|
||||
"subtitle": "Thanks to {count} supporters who made this project possible",
|
||||
"specialThanks": "Special Thanks",
|
||||
"allSupporters": "All Supporters",
|
||||
"totalCount": "{count} supporters in total"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "Mostrar código QR de WeChat",
|
||||
"hideWechatQR": "Ocultar código QR de WeChat"
|
||||
},
|
||||
"footer": "¡Gracias por usar el gestor de LoRA! ❤️"
|
||||
"footer": "¡Gracias por usar el gestor de LoRA! ❤️",
|
||||
"supporters": {
|
||||
"title": "Gracias a todos los seguidores",
|
||||
"subtitle": "Gracias a {count} seguidores que hicieron este proyecto posible",
|
||||
"specialThanks": "Agradecimientos especiales",
|
||||
"allSupporters": "Todos los seguidores",
|
||||
"totalCount": "{count} seguidores en total"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "Afficher le QR Code WeChat",
|
||||
"hideWechatQR": "Masquer le QR Code WeChat"
|
||||
},
|
||||
"footer": "Merci d'utiliser le Gestionnaire LoRA ! ❤️"
|
||||
"footer": "Merci d'utiliser le Gestionnaire LoRA ! ❤️",
|
||||
"supporters": {
|
||||
"title": "Merci à tous les supporters",
|
||||
"subtitle": "Merci aux {count} supporters qui ont rendu ce projet possible",
|
||||
"specialThanks": "Remerciements spéciaux",
|
||||
"allSupporters": "Tous les supporters",
|
||||
"totalCount": "{count} supporters au total"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "הצג קוד QR של WeChat",
|
||||
"hideWechatQR": "הסתר קוד QR של WeChat"
|
||||
},
|
||||
"footer": "תודה על השימוש במנהל LoRA! ❤️"
|
||||
"footer": "תודה על השימוש במנהל LoRA! ❤️",
|
||||
"supporters": {
|
||||
"title": "תודה לכל התומכים",
|
||||
"subtitle": "תודה ל־{count} תומכים שהפכו את הפרויקט הזה לאפשרי",
|
||||
"specialThanks": "תודה מיוחדת",
|
||||
"allSupporters": "כל התומכים",
|
||||
"totalCount": "{count} תומכים בסך הכל"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "WeChat QRコードを表示",
|
||||
"hideWechatQR": "WeChat QRコードを非表示"
|
||||
},
|
||||
"footer": "LoRA Managerをご利用いただきありがとうございます! ❤️"
|
||||
"footer": "LoRA Managerをご利用いただきありがとうございます! ❤️",
|
||||
"supporters": {
|
||||
"title": "サポーターの皆様に感謝",
|
||||
"subtitle": "{count} 名のサポーターの皆様に、このプロジェクトを実現していただきありがとうございます",
|
||||
"specialThanks": "特別感謝",
|
||||
"allSupporters": "全サポーター",
|
||||
"totalCount": "サポーター {count} 名"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "WeChat QR 코드 표시",
|
||||
"hideWechatQR": "WeChat QR 코드 숨기기"
|
||||
},
|
||||
"footer": "LoRA Manager를 사용해주셔서 감사합니다! ❤️"
|
||||
"footer": "LoRA Manager를 사용해주셔서 감사합니다! ❤️",
|
||||
"supporters": {
|
||||
"title": "후원자 분들께 감사드립니다",
|
||||
"subtitle": "이 프로젝트를 가능하게 해준 {count}명의 후원자분들께 감사드립니다",
|
||||
"specialThanks": "특별 감사",
|
||||
"allSupporters": "모든 후원자",
|
||||
"totalCount": "총 {count}명의 후원자"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "Показать QR-код WeChat",
|
||||
"hideWechatQR": "Скрыть QR-код WeChat"
|
||||
},
|
||||
"footer": "Спасибо за использование LoRA Manager! ❤️"
|
||||
"footer": "Спасибо за использование LoRA Manager! ❤️",
|
||||
"supporters": {
|
||||
"title": "Спасибо всем сторонникам",
|
||||
"subtitle": "Спасибо {count} сторонникам, которые сделали этот проект возможным",
|
||||
"specialThanks": "Особая благодарность",
|
||||
"allSupporters": "Все сторонники",
|
||||
"totalCount": "Всего {count} сторонников"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "显示微信二维码",
|
||||
"hideWechatQR": "隐藏微信二维码"
|
||||
},
|
||||
"footer": "感谢使用 LoRA 管理器!❤️"
|
||||
"footer": "感谢使用 LoRA 管理器!❤️",
|
||||
"supporters": {
|
||||
"title": "感谢所有支持者",
|
||||
"subtitle": "感谢 {count} 位支持者让这个项目成为可能",
|
||||
"specialThanks": "特别感谢",
|
||||
"allSupporters": "所有支持者",
|
||||
"totalCount": "共 {count} 位支持者"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -1342,7 +1342,14 @@
|
||||
"showWechatQR": "顯示微信二維碼",
|
||||
"hideWechatQR": "隱藏微信二維碼"
|
||||
},
|
||||
"footer": "感謝您使用 LoRA 管理器!❤️"
|
||||
"footer": "感謝您使用 LoRA 管理器!❤️",
|
||||
"supporters": {
|
||||
"title": "感謝所有支持者",
|
||||
"subtitle": "感謝 {count} 位支持者讓這個專案成為可能",
|
||||
"specialThanks": "特別感謝",
|
||||
"allSupporters": "所有支持者",
|
||||
"totalCount": "共 {count} 位支持者"
|
||||
}
|
||||
},
|
||||
"toast": {
|
||||
"general": {
|
||||
|
||||
@@ -9,6 +9,7 @@ objects that can be composed by the route controller.
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
@@ -218,6 +219,45 @@ class HealthCheckHandler:
|
||||
return web.json_response({"status": "ok"})
|
||||
|
||||
|
||||
class SupportersHandler:
|
||||
"""Handler for supporters data."""
|
||||
|
||||
def __init__(self, logger: logging.Logger | None = None) -> None:
|
||||
self._logger = logger or logging.getLogger(__name__)
|
||||
|
||||
def _load_supporters(self) -> dict:
|
||||
"""Load supporters data from JSON file."""
|
||||
try:
|
||||
current_file = os.path.abspath(__file__)
|
||||
root_dir = os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(current_file)))
|
||||
)
|
||||
supporters_path = os.path.join(root_dir, "data", "supporters.json")
|
||||
|
||||
if os.path.exists(supporters_path):
|
||||
with open(supporters_path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
self._logger.debug(f"Failed to load supporters data: {e}")
|
||||
|
||||
return {
|
||||
"specialThanks": [],
|
||||
"allSupporters": [],
|
||||
"totalCount": 0
|
||||
}
|
||||
|
||||
async def get_supporters(self, request: web.Request) -> web.Response:
|
||||
"""Return supporters data as JSON."""
|
||||
try:
|
||||
supporters = self._load_supporters()
|
||||
return web.json_response({"success": True, "supporters": supporters})
|
||||
except Exception as exc:
|
||||
self._logger.error("Error loading supporters: %s", exc, exc_info=True)
|
||||
return web.json_response(
|
||||
{"success": False, "error": str(exc)}, status=500
|
||||
)
|
||||
|
||||
|
||||
class SettingsHandler:
|
||||
"""Sync settings between backend and frontend."""
|
||||
|
||||
@@ -1482,6 +1522,7 @@ class MiscHandlerSet:
|
||||
metadata_archive: MetadataArchiveHandler,
|
||||
filesystem: FileSystemHandler,
|
||||
custom_words: CustomWordsHandler,
|
||||
supporters: SupportersHandler,
|
||||
) -> None:
|
||||
self.health = health
|
||||
self.settings = settings
|
||||
@@ -1494,6 +1535,7 @@ class MiscHandlerSet:
|
||||
self.metadata_archive = metadata_archive
|
||||
self.filesystem = filesystem
|
||||
self.custom_words = custom_words
|
||||
self.supporters = supporters
|
||||
|
||||
def to_route_mapping(
|
||||
self,
|
||||
@@ -1522,6 +1564,7 @@ class MiscHandlerSet:
|
||||
"open_file_location": self.filesystem.open_file_location,
|
||||
"open_settings_location": self.filesystem.open_settings_location,
|
||||
"search_custom_words": self.custom_words.search_custom_words,
|
||||
"get_supporters": self.supporters.get_supporters,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -66,6 +66,27 @@ class ModelPageView:
|
||||
self._logger = logger
|
||||
self._app_version = self._get_app_version()
|
||||
|
||||
def _load_supporters(self) -> dict:
|
||||
"""Load supporters data from JSON file."""
|
||||
try:
|
||||
current_file = os.path.abspath(__file__)
|
||||
root_dir = os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(current_file)))
|
||||
)
|
||||
supporters_path = os.path.join(root_dir, "data", "supporters.json")
|
||||
|
||||
if os.path.exists(supporters_path):
|
||||
with open(supporters_path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
self._logger.debug(f"Failed to load supporters data: {e}")
|
||||
|
||||
return {
|
||||
"specialThanks": [],
|
||||
"allSupporters": [],
|
||||
"totalCount": 0
|
||||
}
|
||||
|
||||
def _get_app_version(self) -> str:
|
||||
version = "1.0.0"
|
||||
short_hash = "stable"
|
||||
|
||||
@@ -26,6 +26,7 @@ MISC_ROUTE_DEFINITIONS: tuple[RouteDefinition, ...] = (
|
||||
RouteDefinition("GET", "/api/lm/settings/libraries", "get_settings_libraries"),
|
||||
RouteDefinition("POST", "/api/lm/settings/libraries/activate", "activate_library"),
|
||||
RouteDefinition("GET", "/api/lm/health-check", "health_check"),
|
||||
RouteDefinition("GET", "/api/lm/supporters", "get_supporters"),
|
||||
RouteDefinition("POST", "/api/lm/open-file-location", "open_file_location"),
|
||||
RouteDefinition("POST", "/api/lm/update-usage-stats", "update_usage_stats"),
|
||||
RouteDefinition("GET", "/api/lm/get-usage-stats", "get_usage_stats"),
|
||||
|
||||
@@ -29,6 +29,7 @@ from .handlers.misc_handlers import (
|
||||
NodeRegistry,
|
||||
NodeRegistryHandler,
|
||||
SettingsHandler,
|
||||
SupportersHandler,
|
||||
TrainedWordsHandler,
|
||||
UsageStatsHandler,
|
||||
build_service_registry_adapter,
|
||||
@@ -119,6 +120,7 @@ class MiscRoutes:
|
||||
metadata_provider_factory=self._metadata_provider_factory,
|
||||
)
|
||||
custom_words = CustomWordsHandler()
|
||||
supporters = SupportersHandler()
|
||||
|
||||
return self._handler_set_factory(
|
||||
health=health,
|
||||
@@ -132,6 +134,7 @@ class MiscRoutes:
|
||||
metadata_archive=metadata_archive,
|
||||
filesystem=filesystem,
|
||||
custom_words=custom_words,
|
||||
supporters=supporters,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ body {
|
||||
--space-1: calc(8px * 1);
|
||||
--space-2: calc(8px * 2);
|
||||
--space-3: calc(8px * 3);
|
||||
--space-4: calc(8px * 4);
|
||||
|
||||
/* Z-index Scale */
|
||||
--z-base: 10;
|
||||
@@ -77,6 +78,7 @@ body {
|
||||
|
||||
/* Border Radius */
|
||||
--border-radius-base: 12px;
|
||||
--border-radius-md: 12px;
|
||||
--border-radius-sm: 8px;
|
||||
--border-radius-xs: 4px;
|
||||
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
/* Support Modal Styles */
|
||||
.support-modal {
|
||||
max-width: 570px;
|
||||
max-width: 1000px;
|
||||
width: 90vw;
|
||||
}
|
||||
|
||||
/* Two-column layout */
|
||||
.support-container {
|
||||
display: flex;
|
||||
gap: var(--space-3);
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.support-left {
|
||||
flex: 0 0 42%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.support-right {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
border-left: 1px solid var(--lora-border);
|
||||
padding-left: var(--space-4);
|
||||
}
|
||||
|
||||
.support-header {
|
||||
@@ -214,6 +234,11 @@
|
||||
.support-links {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.support-modal {
|
||||
width: 95vw;
|
||||
max-width: 95vw;
|
||||
}
|
||||
}
|
||||
|
||||
/* Civitai link styles */
|
||||
@@ -239,4 +264,181 @@
|
||||
.folder-item:hover {
|
||||
border-color: var(--lora-accent);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Supporters Section Styles */
|
||||
.supporters-section {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.supporters-header {
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.supporters-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
margin: 0 0 var(--space-1) 0;
|
||||
font-size: 1.3em !important;
|
||||
color: var(--lora-accent) !important;
|
||||
}
|
||||
|
||||
.supporters-title i {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.supporters-subtitle {
|
||||
margin: 0;
|
||||
font-size: 0.95em;
|
||||
color: var(--text-color);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.supporters-group {
|
||||
margin-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.supporters-group-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 0 0 var(--space-2) 0;
|
||||
font-size: 1em;
|
||||
color: var(--text-color);
|
||||
opacity: 0.8;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.supporters-group-title i {
|
||||
color: var(--lora-accent);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* Special Thanks - Clean Card Style */
|
||||
.special-thanks-group {
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.special-thanks-group .supporters-group-title {
|
||||
margin-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.special-thanks-group .supporters-group-title i {
|
||||
color: #fbbf24;
|
||||
}
|
||||
|
||||
.all-supporters-group .supporters-group-title i {
|
||||
color: var(--lora-error);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.supporters-special-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
.supporter-special-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
background: var(--card-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-left: 3px solid var(--lora-accent);
|
||||
border-radius: var(--border-radius-sm);
|
||||
transition: all 0.2s ease;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.supporter-special-card:hover {
|
||||
border-color: var(--lora-accent);
|
||||
border-left-color: var(--lora-accent);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.supporter-special-card .supporter-special-name {
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
color: var(--text-color);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.supporter-special-card:hover .supporter-special-name {
|
||||
color: var(--lora-accent);
|
||||
}
|
||||
|
||||
/* All Supporters - Elegant Text Flow */
|
||||
.all-supporters-group {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.all-supporters-group .supporters-group-title {
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
.supporters-all-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
line-height: 2.2;
|
||||
max-height: 550px;
|
||||
overflow-y: auto;
|
||||
padding: var(--space-2) 0;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.supporter-name-item {
|
||||
font-size: 0.95em;
|
||||
color: var(--text-color);
|
||||
opacity: 0.85;
|
||||
transition: all 0.2s ease;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.supporter-name-item:hover {
|
||||
opacity: 1;
|
||||
color: var(--lora-accent);
|
||||
}
|
||||
|
||||
.supporter-separator {
|
||||
margin: 0 10px;
|
||||
color: var(--text-color);
|
||||
opacity: 0.25;
|
||||
font-weight: 300;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.support-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.support-left {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.support-right {
|
||||
border-left: none;
|
||||
border-top: 1px solid var(--lora-border);
|
||||
padding-left: 0;
|
||||
padding-top: var(--space-3);
|
||||
}
|
||||
|
||||
.supporters-all-list {
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.supporters-special-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { FilterManager } from '../managers/FilterManager.js';
|
||||
import { initPageState } from '../state/index.js';
|
||||
import { getStorageItem } from '../utils/storageHelpers.js';
|
||||
import { updateElementAttribute } from '../utils/i18nHelpers.js';
|
||||
import { renderSupporters } from '../services/supportersService.js';
|
||||
|
||||
/**
|
||||
* Header.js - Manages the application header behavior across different pages
|
||||
@@ -85,9 +86,15 @@ export class HeaderManager {
|
||||
// Handle support toggle
|
||||
const supportToggle = document.getElementById('supportToggleBtn');
|
||||
if (supportToggle) {
|
||||
supportToggle.addEventListener('click', () => {
|
||||
supportToggle.addEventListener('click', async () => {
|
||||
if (window.modalManager) {
|
||||
window.modalManager.toggleModal('supportModal');
|
||||
// Load supporters data when modal opens
|
||||
try {
|
||||
await renderSupporters();
|
||||
} catch (error) {
|
||||
console.error('Error loading supporters:', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
104
static/js/services/supportersService.js
Normal file
104
static/js/services/supportersService.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Supporters service - Fetches and manages supporters data
|
||||
*/
|
||||
|
||||
let supportersData = null;
|
||||
let isLoading = false;
|
||||
let loadPromise = null;
|
||||
|
||||
/**
|
||||
* Fetch supporters data from the API
|
||||
* @returns {Promise<Object>} Supporters data
|
||||
*/
|
||||
export async function fetchSupporters() {
|
||||
// Return cached data if available
|
||||
if (supportersData) {
|
||||
return supportersData;
|
||||
}
|
||||
|
||||
// Return existing promise if already loading
|
||||
if (isLoading && loadPromise) {
|
||||
return loadPromise;
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
loadPromise = fetch('/api/lm/supporters')
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch supporters: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success && data.supporters) {
|
||||
supportersData = data.supporters;
|
||||
return supportersData;
|
||||
}
|
||||
throw new Error(data.error || 'Failed to load supporters data');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading supporters:', error);
|
||||
// Return empty data on error
|
||||
return {
|
||||
specialThanks: [],
|
||||
allSupporters: [],
|
||||
totalCount: 0
|
||||
};
|
||||
})
|
||||
.finally(() => {
|
||||
isLoading = false;
|
||||
loadPromise = null;
|
||||
});
|
||||
|
||||
return loadPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cached supporters data
|
||||
*/
|
||||
export function clearSupportersCache() {
|
||||
supportersData = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render supporters in the support modal
|
||||
*/
|
||||
export async function renderSupporters() {
|
||||
const supporters = await fetchSupporters();
|
||||
|
||||
// Update subtitle with total count
|
||||
const subtitleEl = document.getElementById('supportersSubtitle');
|
||||
if (subtitleEl) {
|
||||
// Get the translation key and replace count
|
||||
const originalText = subtitleEl.textContent;
|
||||
// Replace the count in the text (simple approach)
|
||||
subtitleEl.textContent = originalText.replace(/\d+/, supporters.totalCount);
|
||||
}
|
||||
|
||||
// Render special thanks
|
||||
const specialThanksGrid = document.getElementById('specialThanksGrid');
|
||||
if (specialThanksGrid && supporters.specialThanks) {
|
||||
specialThanksGrid.innerHTML = supporters.specialThanks
|
||||
.map(supporter => `
|
||||
<div class="supporter-special-card" title="${supporter}">
|
||||
<span class="supporter-special-name">${supporter}</span>
|
||||
</div>
|
||||
`)
|
||||
.join('');
|
||||
}
|
||||
|
||||
// Render all supporters
|
||||
const supportersGrid = document.getElementById('supportersGrid');
|
||||
if (supportersGrid && supporters.allSupporters) {
|
||||
supportersGrid.innerHTML = supporters.allSupporters
|
||||
.map((supporter, index, array) => {
|
||||
const separator = index < array.length - 1
|
||||
? '<span class="supporter-separator">·</span>'
|
||||
: '';
|
||||
return `
|
||||
<span class="supporter-name-item" title="${supporter}">${supporter}</span>${separator}
|
||||
`;
|
||||
})
|
||||
.join('');
|
||||
}
|
||||
}
|
||||
@@ -2,90 +2,133 @@
|
||||
<div id="supportModal" class="modal">
|
||||
<div class="modal-content support-modal">
|
||||
<button class="close" onclick="modalManager.closeModal('supportModal')">×</button>
|
||||
<div class="support-header">
|
||||
<i class="fas fa-heart support-icon"></i>
|
||||
<h2>{{ t('support.title') }}</h2>
|
||||
</div>
|
||||
<div class="support-content">
|
||||
<p>{{ t('support.message') }}</p>
|
||||
|
||||
<div class="support-section">
|
||||
<h3><i class="fas fa-comment"></i> {{ t('support.feedback.title') }}</h3>
|
||||
<p>{{ t('support.feedback.description') }}</p>
|
||||
<div class="support-links">
|
||||
<a href="https://github.com/willmiao/ComfyUI-Lora-Manager/issues/new" class="social-link" target="_blank">
|
||||
<i class="fab fa-github"></i>
|
||||
<span>{{ t('support.links.submitGithubIssue') }}</span>
|
||||
</a>
|
||||
<a href="https://discord.gg/vcqNrWVFvM" class="social-link" target="_blank">
|
||||
<i class="fab fa-discord"></i>
|
||||
<span>{{ t('support.links.joinDiscord') }}</span>
|
||||
</a>
|
||||
|
||||
<div class="support-container">
|
||||
<!-- Left Side: Support Options -->
|
||||
<div class="support-left">
|
||||
<div class="support-header">
|
||||
<i class="fas fa-heart support-icon"></i>
|
||||
<h2>{{ t('support.title') }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="support-section">
|
||||
<h3><i class="fas fa-rss"></i> {{ t('support.sections.followUpdates') }}</h3>
|
||||
<div class="support-links">
|
||||
<a href="https://www.youtube.com/@pixelpaws-ai" class="social-link" target="_blank">
|
||||
<i class="fab fa-youtube"></i>
|
||||
<span>{{ t('support.links.youtubeChannel') }}</span>
|
||||
</a>
|
||||
<a href="https://civitai.com/user/PixelPawsAI" class="social-link civitai-link" target="_blank">
|
||||
<svg class="civitai-icon" viewBox="0 0 225 225" width="20" height="20">
|
||||
<g transform="translate(0,225) scale(0.1,-0.1)" fill="currentColor">
|
||||
<path d="M950 1899 c-96 -55 -262 -150 -367 -210 -106 -61 -200 -117 -208
|
||||
-125 -13 -13 -15 -76 -15 -443 0 -395 1 -429 18 -443 9 -9 116 -73 237 -143
|
||||
121 -70 283 -163 359 -208 76 -45 146 -80 155 -80 9 1 183 98 386 215 l370
|
||||
215 2 444 3 444 -376 215 c-206 118 -378 216 -382 217 -4 1 -86 -43 -182 -98z
|
||||
m346 -481 l163 -93 1 -57 0 -58 -89 0 c-87 0 -91 1 -166 44 l-78 45 -51 -30
|
||||
c-28 -17 -61 -35 -73 -41 -21 -10 -23 -18 -23 -99 l0 -87 71 -41 c39 -23 73
|
||||
-41 76 -41 3 0 37 18 75 40 68 39 72 40 164 40 l94 0 0 -53 c0 -60 23 -41
|
||||
-198 -168 l-133 -77 -92 52 c-51 29 -126 73 -167 97 l-75 45 0 193 0 192 164
|
||||
95 c91 52 167 94 169 94 2 0 78 -42 168 -92z"/>
|
||||
</g>
|
||||
</svg>
|
||||
<span>{{ t('support.links.civitaiProfile') }}</span>
|
||||
</a>
|
||||
<div class="support-content">
|
||||
<p>{{ t('support.message') }}</p>
|
||||
|
||||
<div class="support-section">
|
||||
<h3><i class="fas fa-comment"></i> {{ t('support.feedback.title') }}</h3>
|
||||
<p>{{ t('support.feedback.description') }}</p>
|
||||
<div class="support-links">
|
||||
<a href="https://github.com/willmiao/ComfyUI-Lora-Manager/issues/new" class="social-link" target="_blank">
|
||||
<i class="fab fa-github"></i>
|
||||
<span>{{ t('support.links.submitGithubIssue') }}</span>
|
||||
</a>
|
||||
<a href="https://discord.gg/vcqNrWVFvM" class="social-link" target="_blank">
|
||||
<i class="fab fa-discord"></i>
|
||||
<span>{{ t('support.links.joinDiscord') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="support-section">
|
||||
<h3><i class="fas fa-rss"></i> {{ t('support.sections.followUpdates') }}</h3>
|
||||
<div class="support-links">
|
||||
<a href="https://www.youtube.com/@pixelpaws-ai" class="social-link" target="_blank">
|
||||
<i class="fab fa-youtube"></i>
|
||||
<span>{{ t('support.links.youtubeChannel') }}</span>
|
||||
</a>
|
||||
<a href="https://civitai.com/user/PixelPawsAI" class="social-link civitai-link" target="_blank">
|
||||
<svg class="civitai-icon" viewBox="0 0 225 225" width="20" height="20">
|
||||
<g transform="translate(0,225) scale(0.1,-0.1)" fill="currentColor">
|
||||
<path d="M950 1899 c-96 -55 -262 -150 -367 -210 -106 -61 -200 -117 -208
|
||||
-125 -13 -13 -15 -76 -15 -443 0 -395 1 -429 18 -443 9 -9 116 -73 237 -143
|
||||
121 -70 283 -163 359 -208 76 -45 146 -80 155 -80 9 1 183 98 386 215 l370
|
||||
215 2 444 3 444 -376 215 c-206 118 -378 216 -382 217 -4 1 -86 -43 -182 -98z
|
||||
m346 -481 l163 -93 1 -57 0 -58 -89 0 c-87 0 -91 1 -166 44 l-78 45 -51 -30
|
||||
c-28 -17 -61 -35 -73 -41 -21 -10 -23 -18 -23 -99 l0 -87 71 -41 c39 -23 73
|
||||
-41 76 -41 3 0 37 18 75 40 68 39 72 40 164 40 l94 0 0 -53 c0 -60 23 -41
|
||||
-198 -168 l-133 -77 -92 52 c-51 29 -126 73 -167 97 l-75 45 0 193 0 192 164
|
||||
95 c91 52 167 94 169 94 2 0 78 -42 168 -92z"/>
|
||||
</g>
|
||||
</svg>
|
||||
<span>{{ t('support.links.civitaiProfile') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="support-section">
|
||||
<h3><i class="fas fa-coffee"></i> {{ t('support.sections.buyMeCoffee') }}</h3>
|
||||
<p>{{ t('support.sections.coffeeDescription') }}</p>
|
||||
<a href="https://ko-fi.com/pixelpawsai" class="kofi-button" target="_blank">
|
||||
<i class="fas fa-mug-hot"></i>
|
||||
<span>{{ t('support.links.supportKofi') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Patreon Support Section -->
|
||||
<div class="support-section">
|
||||
<h3><i class="fab fa-patreon"></i> {{ t('support.sections.becomePatron') }}</h3>
|
||||
<p>{{ t('support.sections.patronDescription') }}</p>
|
||||
<a href="https://patreon.com/PixelPawsAI" class="patreon-button" target="_blank">
|
||||
<i class="fab fa-patreon"></i>
|
||||
<span>{{ t('support.links.supportPatreon') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- New section for Chinese payment methods -->
|
||||
<div class="support-section">
|
||||
<h3><i class="fas fa-qrcode"></i> {{ t('support.sections.wechatSupport') }}</h3>
|
||||
<p>{{ t('support.sections.wechatDescription') }}</p>
|
||||
<button class="secondary-btn qrcode-toggle" id="toggleQRCode">
|
||||
<i class="fas fa-qrcode"></i>
|
||||
<span class="toggle-text">{{ t('support.sections.showWechatQR') }}</span>
|
||||
<i class="fas fa-chevron-down toggle-icon"></i>
|
||||
</button>
|
||||
<div class="qrcode-container" id="qrCodeContainer">
|
||||
<img src="/loras_static/images/wechat-qr.webp" alt="WeChat Pay QR Code" class="qrcode-image">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="support-footer">
|
||||
<p>{{ t('support.footer') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="support-section">
|
||||
<h3><i class="fas fa-coffee"></i> {{ t('support.sections.buyMeCoffee') }}</h3>
|
||||
<p>{{ t('support.sections.coffeeDescription') }}</p>
|
||||
<a href="https://ko-fi.com/pixelpawsai" class="kofi-button" target="_blank">
|
||||
<i class="fas fa-mug-hot"></i>
|
||||
<span>{{ t('support.links.supportKofi') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Patreon Support Section -->
|
||||
<div class="support-section">
|
||||
<h3><i class="fab fa-patreon"></i> {{ t('support.sections.becomePatron') }}</h3>
|
||||
<p>{{ t('support.sections.patronDescription') }}</p>
|
||||
<a href="https://patreon.com/PixelPawsAI" class="patreon-button" target="_blank">
|
||||
<i class="fab fa-patreon"></i>
|
||||
<span>{{ t('support.links.supportPatreon') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
<!-- Right Side: Supporters -->
|
||||
<div class="support-right">
|
||||
<div class="supporters-section">
|
||||
<div class="supporters-header">
|
||||
<h2 class="supporters-title">
|
||||
<i class="fas fa-hands-helping"></i>
|
||||
{{ t('support.supporters.title') }}
|
||||
</h2>
|
||||
<p class="supporters-subtitle" id="supportersSubtitle">
|
||||
{{ t('support.supporters.subtitle', count=0) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Special Thanks Section -->
|
||||
<div class="supporters-group special-thanks-group">
|
||||
<h3 class="supporters-group-title">
|
||||
<i class="fas fa-star"></i>
|
||||
{{ t('support.supporters.specialThanks') }}
|
||||
</h3>
|
||||
<div class="supporters-special-grid" id="specialThanksGrid">
|
||||
<!-- Supporters will be loaded dynamically -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New section for Chinese payment methods -->
|
||||
<div class="support-section">
|
||||
<h3><i class="fas fa-qrcode"></i> {{ t('support.sections.wechatSupport') }}</h3>
|
||||
<p>{{ t('support.sections.wechatDescription') }}</p>
|
||||
<button class="secondary-btn qrcode-toggle" id="toggleQRCode">
|
||||
<i class="fas fa-qrcode"></i>
|
||||
<span class="toggle-text">{{ t('support.sections.showWechatQR') }}</span>
|
||||
<i class="fas fa-chevron-down toggle-icon"></i>
|
||||
</button>
|
||||
<div class="qrcode-container" id="qrCodeContainer">
|
||||
<img src="/loras_static/images/wechat-qr.webp" alt="WeChat Pay QR Code" class="qrcode-image">
|
||||
<!-- All Supporters Section -->
|
||||
<div class="supporters-group all-supporters-group">
|
||||
<h3 class="supporters-group-title">
|
||||
<i class="fas fa-heart"></i>
|
||||
{{ t('support.supporters.allSupporters') }}
|
||||
</h3>
|
||||
<div class="supporters-all-list" id="supportersGrid">
|
||||
<!-- Supporters will be loaded dynamically -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="support-footer">
|
||||
<p>{{ t('support.footer') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user