فهرست منبع

feat(settings): prominent sponsor banner on General tab

      Matomo shows only 1.18% of website visitors reach /sponsors despite
      29% hitting /installation. The ask was discoverable on the marketing
      site but invisible in-app where users actually live.

      Full-width gradient banner sits above the three-column layout on the
      default landing tab and links to bambuddy.cool/sponsors.html with a
      ?from=app-settings tracking param so conversion lift is measurable
      in Matomo. Three new sponsors.* keys translated to all 11 locales.
maziggy 2 ماه پیش
والد
کامیت
5c16ef3e58

+ 1 - 0
README.md

@@ -156,6 +156,7 @@ Optional but recommended — drop the [`slicer-api/` Compose stack](slicer-api/R
 - Skip objects during print
 - AMS slot RFID re-read
 - **AMS slot Load / Unload from the printer card** — Hover any AMS slot or external spool, click the menu button, and load that tray or unload the currently-loaded one without going to the touchscreen; supports dual-extruder H2D (Ext-L / Ext-R drive their own nozzle)
+- **AMS Filament Backup status + control** — Mirrors BambuStudio's per-printer "AMS Filament Backup" auto-switch (when a spool runs out, the printer rolls over to a same-material spool in another slot). A small badge in the Filaments section header on each printer card shows the live state (blue circular-arrow icon = ON, dim = OFF, "?" = A1 family with no `cfg` field yet); click to toggle. State syncs in real time whether you toggled from Bambuddy, BambuStudio, or the printer's touchscreen. Bambuddy's **Prefer Lowest Remaining Filament** sort now respects this setting — when Backup is OFF the dispatcher skips the prefer-lowest sort entirely so it won't reach for a near-empty spool the printer can't roll off of.
 - AMS slot configuration (model-filtered presets, K profiles, color picker, pre-population for configured slots)
 - AMS info card (hover for serial number, firmware version) with custom friendly names that persist across printers
 - **AMS remote drying** — Start, monitor, and stop drying sessions for AMS 2 Pro and AMS-HT directly from the Printers page with filament-based temperature/duration presets, optional spool rotation; automatic PSU detection and HMS power error reporting

+ 7 - 0
frontend/src/i18n/locales/de.ts

@@ -3605,6 +3605,13 @@ export default {
     architecture: 'Architektur',
   },
 
+  // Sponsor surface (System page)
+  sponsors: {
+    sectionTitle: 'Unabhängig & von der Community finanziert',
+    tagline: 'Bambuddy ist kostenlos und bleibt es, weil Menschen es freiwillig unterstützen. Kein VC, kein Cloud-Zwang.',
+    viewSupporters: 'Unterstützer ansehen',
+  },
+
   // Library (K Profiles)
   library: {
     title: 'Filament-Bibliothek',

+ 7 - 0
frontend/src/i18n/locales/en.ts

@@ -3617,6 +3617,13 @@ export default {
     architecture: 'Architecture',
   },
 
+  // Sponsor surface (System page)
+  sponsors: {
+    sectionTitle: 'Independent & community-funded',
+    tagline: 'Bambuddy is free and stays that way because people choose to support it. No VC, no cloud lock-in.',
+    viewSupporters: 'View supporters',
+  },
+
   // Library (K Profiles)
   library: {
     title: 'Filament Library',

+ 7 - 0
frontend/src/i18n/locales/es.ts

@@ -3608,6 +3608,13 @@ export default {
     architecture: 'Arquitectura',
   },
 
+  // Sponsor surface (System page)
+  sponsors: {
+    sectionTitle: 'Independiente y financiado por la comunidad',
+    tagline: 'Bambuddy es gratuito y seguirá siéndolo porque hay quien decide apoyarlo. Sin VC, sin dependencia de la nube.',
+    viewSupporters: 'Ver patrocinadores',
+  },
+
   // Library (K Profiles)
   library: {
     title: 'Biblioteca de filamentos',

+ 7 - 0
frontend/src/i18n/locales/fr.ts

@@ -3594,6 +3594,13 @@ export default {
     architecture: 'Architecture',
   },
 
+  // Sponsor surface (System page)
+  sponsors: {
+    sectionTitle: 'Indépendant & financé par la communauté',
+    tagline: 'Bambuddy est gratuit et le reste parce que des personnes choisissent de le soutenir. Pas de VC, pas de verrouillage cloud.',
+    viewSupporters: 'Voir les soutiens',
+  },
+
   // Library (K Profiles)
   library: {
     title: 'Bibliothèque Filament',

+ 7 - 0
frontend/src/i18n/locales/it.ts

@@ -3593,6 +3593,13 @@ export default {
     architecture: 'Architettura',
   },
 
+  // Sponsor surface (System page)
+  sponsors: {
+    sectionTitle: 'Indipendente e finanziato dalla community',
+    tagline: 'Bambuddy è gratuito e resta tale perché qualcuno sceglie di sostenerlo. Niente VC, niente lock-in cloud.',
+    viewSupporters: 'Vedi i sostenitori',
+  },
+
   // Library (K Profiles)
   library: {
     title: 'Libreria filamenti',

+ 7 - 0
frontend/src/i18n/locales/ja.ts

@@ -3605,6 +3605,13 @@ export default {
     architecture: 'アーキテクチャ',
   },
 
+  // Sponsor surface (System page)
+  sponsors: {
+    sectionTitle: '独立・コミュニティ運営',
+    tagline: 'Bambuddyは無料で、これからも無料です。支援してくださる方々のおかげで、VCもクラウドロックインもありません。',
+    viewSupporters: 'サポーター一覧',
+  },
+
   // Library (K Profiles)
   library: {
     title: 'フィラメントライブラリ',

+ 5 - 0
frontend/src/i18n/locales/ko.ts

@@ -3404,6 +3404,11 @@ export default {
     platform: '플랫폼',
     architecture: '아키텍처'
   },
+  sponsors: {
+    sectionTitle: '독립적·커뮤니티 후원',
+    tagline: 'Bambuddy는 무료이며, 자발적으로 후원하는 사용자 덕분에 계속 무료로 유지됩니다. VC도 없고, 클라우드 종속도 없습니다.',
+    viewSupporters: '후원자 보기'
+  },
   library: {
     title: '필라멘트 라이브러리',
     addFilament: '필라멘트 추가',

+ 7 - 0
frontend/src/i18n/locales/pt-BR.ts

@@ -3593,6 +3593,13 @@ export default {
     architecture: 'Arquitetura',
   },
 
+  // Sponsor surface (System page)
+  sponsors: {
+    sectionTitle: 'Independente e financiado pela comunidade',
+    tagline: 'O Bambuddy é gratuito e continua assim porque há quem escolha apoiá-lo. Sem VC, sem dependência de nuvem.',
+    viewSupporters: 'Ver apoiadores',
+  },
+
   // Library (K Profiles)
   library: {
     title: 'Biblioteca de Filamentos',

+ 7 - 0
frontend/src/i18n/locales/tr.ts

@@ -3594,6 +3594,13 @@ export default {
     architecture: 'Mimari',
   },
 
+  // Sponsor yüzeyi (Sistem sayfası)
+  sponsors: {
+    sectionTitle: 'Bağımsız ve topluluk destekli',
+    tagline: 'Bambuddy ücretsizdir ve böyle kalır çünkü insanlar onu desteklemeyi seçer. VC yok, bulut bağımlılığı yok.',
+    viewSupporters: 'Destekçileri görüntüle',
+  },
+
   // Kütüphane (K Profilleri)
   library: {
     title: 'Filament Kütüphanesi',

+ 7 - 0
frontend/src/i18n/locales/zh-CN.ts

@@ -3593,6 +3593,13 @@ export default {
     architecture: '架构',
   },
 
+  // Sponsor surface (System page)
+  sponsors: {
+    sectionTitle: '独立运营·社区支持',
+    tagline: 'Bambuddy 完全免费,并将持续免费——这要感谢主动支持的用户。没有风投,也没有云端绑定。',
+    viewSupporters: '查看支持者',
+  },
+
   // Library (K Profiles)
   library: {
     title: '耗材库',

+ 7 - 0
frontend/src/i18n/locales/zh-TW.ts

@@ -3593,6 +3593,13 @@ export default {
     architecture: '架構',
   },
 
+  // Sponsor surface (System page)
+  sponsors: {
+    sectionTitle: '獨立運作·社群支持',
+    tagline: 'Bambuddy 完全免費,並將持續免費——感謝主動支持的使用者。沒有創投,也沒有雲端綁定。',
+    viewSupporters: '查看支持者',
+  },
+
   // Library (K Profiles)
   library: {
     title: '耗材庫',

+ 32 - 1
frontend/src/pages/SettingsPage.tsx

@@ -1,5 +1,5 @@
 import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
-import { Loader2, Plus, Plug, AlertTriangle, RotateCcw, Bell, Download, RefreshCw, ExternalLink, Globe, Droplets, Thermometer, FileText, Edit2, Send, CheckCircle, XCircle, History, Trash2, Zap, TrendingUp, Calendar, DollarSign, Power, PowerOff, Key, Copy, Database, X, Shield, Printer, Cylinder, Wifi, Home, Video, Users, Lock, Unlock, ChevronDown, Save, Mail, Flame, Layers, ListOrdered, Code, Search, Scale, Settings as SettingsIcon, ScanEye, Cog, QrCode } from 'lucide-react';
+import { Loader2, Plus, Plug, AlertTriangle, RotateCcw, Bell, Download, RefreshCw, ExternalLink, Globe, Droplets, Thermometer, FileText, Edit2, Send, CheckCircle, XCircle, History, Trash2, Zap, TrendingUp, Calendar, DollarSign, Power, PowerOff, Key, Copy, Database, X, Shield, Printer, Cylinder, Wifi, Home, Video, Users, Lock, Unlock, ChevronDown, Save, Mail, Flame, Layers, ListOrdered, Code, Search, Scale, Settings as SettingsIcon, ScanEye, Cog, QrCode, Heart } from 'lucide-react';
 import { useTranslation } from 'react-i18next';
 import { useNavigate, useSearchParams } from 'react-router-dom';
 import { api } from '../api/client';
@@ -1459,6 +1459,36 @@ export function SettingsPage() {
       </nav>
       <div className="flex-1 min-w-0">
       {activeTab === 'general' && (
+      <>
+      {/* Sponsor banner — prominent independence callout */}
+      <a
+        href="https://bambuddy.cool/sponsors.html?from=app-settings"
+        target="_blank"
+        rel="noopener noreferrer"
+        className="group block mb-4 lg:mb-6 rounded-xl border border-bambu-green/30 bg-gradient-to-br from-bambu-green/15 via-bambu-green/5 to-transparent hover:border-bambu-green/50 hover:from-bambu-green/20 transition-colors"
+      >
+        <div className="flex flex-col md:flex-row items-start md:items-center gap-4 p-4 md:p-5">
+          <div className="p-3 rounded-lg bg-bambu-green/20 text-bambu-green flex-shrink-0">
+            <Heart className="w-6 h-6" />
+          </div>
+          <div className="flex-1 min-w-0">
+            <p className="text-base font-semibold text-white">
+              {t('sponsors.sectionTitle', 'Independent & community-funded')}
+            </p>
+            <p className="text-sm text-bambu-gray mt-0.5">
+              {t(
+                'sponsors.tagline',
+                'Bambuddy is free and stays that way because people choose to support it. No VC, no cloud lock-in.'
+              )}
+            </p>
+          </div>
+          <div className="flex items-center gap-2 px-4 py-2 rounded-lg bg-bambu-green/20 text-bambu-green group-hover:bg-bambu-green/30 text-sm font-medium whitespace-nowrap self-start md:self-auto">
+            {t('sponsors.viewSupporters', 'View supporters')}
+            <ExternalLink className="w-4 h-4" />
+          </div>
+        </div>
+      </a>
+
       <div className="flex flex-col lg:flex-row gap-4 lg:gap-6">
         {/* Left Column - General Settings */}
         <div className="space-y-3 flex-1 lg:max-w-xl">
@@ -2551,6 +2581,7 @@ export function SettingsPage() {
           <ExternalLinksSettings />
         </div>
       </div>
+      </>
       )}
 
       {/* Network Tab */}